暫無鏈接
老大
【題目描述】
因爲 OB 今年拿下塊金牌,學校贊助擴建勞模辦公室爲勞模辦公室羣,爲了體現 OI 的特色,辦公室羣被設計成了樹形個點條邊的無向連通圖),由於新建的辦公室太大以至於要將獎盃要分放在兩個不同的地方以便同學們丟硬幣進去開光,OB 想請你幫幫他看看獎盃放在哪兩個辦公室使得在任意一個在勞模辦公室做題的小朋友能最快地找到獎盃來開光。
一句話題意:給出一個個點的樹,在兩個合適且不同的點放上獎盃,使得每個點到最近的獎盃距離最大值最小。
【輸入】
第一行,一個整數。
接下來的行,每行兩個數。
【輸出】
一個數,表示最小的最大距離。
【輸入樣例】
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
【數據規模與約定】
對於前的數據,。
對於前的數據,。
對於的數據,保證樹的形態隨機。
對於的數據,保證。
題解
二分最大距離,用將軍令來看是否能用2個點覆蓋,複雜度
代碼
#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();}