[2018.10.24 T3] 老大

暫無鏈接

老大

【題目描述】

因爲 OB 今年拿下44塊金牌,學校贊助擴建勞模辦公室爲勞模辦公室羣,爲了體現 OI 的特色,辦公室羣被設計成了樹形nn個點n1n−1條邊的無向連通圖),由於新建的辦公室太大以至於要將獎盃要分放在兩個不同的地方以便同學們丟硬幣進去開光,OB 想請你幫幫他看看獎盃放在哪兩個辦公室使得在任意一個在勞模辦公室做題的小朋友能最快地找到獎盃來開光。

一句話題意:給出一個nn個點的樹,在兩個合適且不同的點放上獎盃,使得每個點到最近的獎盃距離最大值最小。

【輸入】

第一行,一個整數nn

接下來的n1n−1行,每行兩個數x,yx,y

【輸出】

一個數,表示最小的最大距離。

【輸入樣例】

5
1 2
2 3
3 4
4 5

【輸出樣例】

1

【提示】
輸入樣例#2

8
1 2
1 3
2 4
2 5
3 6
3 7
1 8

輸入樣例#2

2

【數據規模與約定】

對於前60%60\%的數據,n100n≤100

對於前80%80\%的數據,n2000n≤2000

對於80%80\%的數據,保證樹的形態隨機。

對於100%100\%的數據,保證3n2000003≤n≤200000

題解

二分最大距離,用將軍令checkcheck看是否能用2個點覆蓋,複雜度O(nlogn)O(n\log n)

代碼
#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5;
int head[M],nxt[M<<1],to[M<<1],dis[M],l,r,mid,cnt,n,ans;
void add(int f,int t){nxt[++cnt]=head[f],head[f]=cnt,to[cnt]=t;}
void dfs(int f,int v,int k)
{
	int mx=0,mn=M;
	for(int i=head[v];i;i=nxt[i])if(to[i]!=f)dfs(v,to[i],k),mx=max(mx,dis[to[i]]+1),mn=min(mn,dis[to[i]]+1);
	dis[v]=(mx+mn<0?mn:mx);
	if(dis[v]>=k)dis[v]=-k-1,++ans;
}
bool check(int k){dfs(ans=0,1,k);if(dis[1]>=0)++ans;return ans>2;}
void in(){scanf("%d",&n);for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),add(a,b),add(b,a);}
void ac(){for(l=0,r=n;l^r;)mid=l+r>>1,check(mid)?l=mid+1:r=mid;printf("%d",l);}
int main(){in(),ac();}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章