タイトル説明
簡単に言えば、これらの点のレイアウトは、木であり、等しい長さの各側は、1です。牛パスの特定のセットのために、スマート牛たちは、コレクションのパスの直径を呼び出し、パス、上の任意の点の値を計算します。直径が大きすぎると、牛が行使することを拒否します。ファーマージョンすべての点標識1..V(2 <= V <= 100,000)。より多くの短径を得るために、彼は、既存の道路の一部をブロックするように選択することができますので、あなたは、それによって設定され、いくつかの経路の直径を小さく、パスのより多くのセットを取得することができます。我々は木で始まり、FJはS(1 <= S <=ブロックするように選択することができる V-1) S + 1つのパスのセットを得るように、双方向パス。あなたがしなければならないことは、すべてのパスが、彼は可能な限り小さく設定された最大直径を得たように、最良のブロッキングスキームを計算しています。
頂点a_iを(1 <= a_iを<=:ファーマージョンのように表現それぞれ、あなたのすべてのV-1、双方向の道を教え V) とB_i(1 <= B_i <= ;!a_iを= B_i V) の接続。
次の例を見てみましょう:直線経路セット(7本の木頂点)3. 1 --- 2 --- --- --- 4. 5. 6 --- --- 7 FJを遮断可能な2つの場合。以下のように、彼の可能な選択肢は、道路です:1 --- 2 | 3 --- 4 | 5 --- 6 --- 7 最長の直径が2になるように、それは(もちろんだけでなく、1)最良の答えです。
エントリー
第2〜V線:二つの空間に分離整数a_iをとB_i
輸出
サンプル入力 のコピー
7 2
6 7
3 4
5 6
1 2
3 2
4 5
サンプル出力のコピー
2つの
アイデア:
- この質問はまだ非常に良い考え、ほとんどの値は、最初の反応の三分の二のようなものであるかを確認のようなものを感じ、その後、いくつかの状態の転送を見つけるために、DPを考えるのは簡単です。
-
私たちの半分最小値、およびそれが有効であることを確認し、即ち、答えはありませんより大きい2分の最大鎖長を確保するために、
-
我々は、DPを設定する[ I ]最初に発現iは I、正当なエンドポイントは鎖の最も長い鎖長がルートのパスと交差しないノードをルートとするサブツリー
-
その後、我々はDPを使用することができます[i]の 2つの答えの正当性の現在の分離を決定するために、カットオフされるようにどのように多くのエッジを計算します
-
気持ちは非常にシンプルですが、慎重に転送がプレーするのは簡単ではありません見つけたと思うが、
-
明らかに決定直接mはX (F [ S O N- ]は)我々はパスの最長の鎖末端は、ルートノードと交差しない二人の息子を選択したとき、それが正当な保証するものではないが、我々は考えるので、不可能ですチェーン、ニーズから切り離され、長さが大きすぎる時にそれらを一緒に見つけ、あなただけの2例があります
-
(切断縁部がチェーンの先頭でない場合、または短い鎖を切断し、その後、他の違法な状況が存在してもよい、まだ一度切断しなければならない)最良の上部を切断する最も長い側鎖
-
カット後、それは(切断終了後に、これら2つの点が通信ブロックに含まれていないため、コースには影響されない)親ノードに影響を与えないであろう。
-
これまでのところ、この問題は、実質的に連続最長チェーンは、チェーンの経路と交差しない二つの隣接するエンドポイントを決定することは、ルートノードであり、現在のポイントの高い順に行[A]限り、すべての息子のDPとして、秒を切断することができますそれは合法的にDP割り当てることができるならば、法律上の[i]を、そうでない場合は、探し続ける、とは数プラス1を切りました。
コード:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+10; 4 struct node 5 { 6 int to; 7 int next; 8 }way[maxn]; 9 int head[maxn]; 10 int tot=0; 11 int fa[maxn]; 12 int top,sumn; 13 int x,y,s,n; 14 int a[maxn]; 15 int add(int x,int y) 16 { 17 way[++tot].next=head[x]; 18 way[tot].to=y; 19 head[x]=tot; 20 } 21 int dfs(int x,int f,int cut) 22 { 23 fa[x]=0; 24 for(int i=head[x];i;i=way[i].next) 25 { 26 if(way[i].to!=f) 27 { 28 dfs(way[i].to,x,cut); 29 } 30 } 31 top=0; 32 for(int i=head[x];i;i=way[i].next) 33 { 34 if(way[i].to!=f) 35 { 36 a[++top]=fa[way[i].to]+1; 37 } 38 } 39 sort(a+1,a+1+top); 40 while(top&&a[top]+a[top-1]>cut) 41 { 42 top--; 43 sumn++; 44 } 45 fa[x]=a[top]; 46 } 47 int check(int x) 48 { 49 sumn=0; 50 dfs(1,0,x); 51 return sumn<=s; 52 } 53 int main() 54 { 55 cin>>n>>s; 56 for(int i=1;i<=n-1;i++) 57 { 58 cin>>x>>y; 59 add(x,y); 60 add(y,x); 61 } 62 63 int l=0; 64 int r=n; 65 while(l<r) 66 { 67 int mid=(l+r)>>1; 68 if(check(mid)) 69 { 70 r=mid; 71 } 72 else 73 { 74 l=mid+1; 75 } 76 } 77 cout<<l<<endl; 78 return 0; 79 }