天天和樹
阿新 • • 發佈:2017-09-30
include std style ostream names tro last back 選擇
問題描述】
個樹由 n 個點,n 1 條邊組成,結點編號為 1:::n。樹上任意兩個點之間路徑唯一。
定義一個點到一條路徑的距離為:該點到路徑上最近的一個點需要經過的邊的數量。
現在想知道怎樣選兩個點確定一條路徑,使得距離這個路徑最遠的點盡量近。要求你輸出距離路徑最遠的點距離路徑的距離。
【輸入格式】
第一行個整數 n。其中 1<=n<=100,000 接下來 n-1行,每行兩個整數 u 和 v,表示結點 u 和結點 v 之間有一條邊。
【輸出格式】
一個整數,為題目要求的答案。
【樣例輸入】
8
1 2
2 3
1 4
4 5
1 6
6 7
7 8
4
【樣例輸出】
2
【樣例解釋】
可以選擇 3 到 7 作為一條鏈,那麽此時距離這條鏈最遠的點是 5,距離為 2。可以發現不存在其他的一條鏈,使得最遠點的距離更短。
【數據規模和約定】
對於 10% 的數據,保證 n = 99998,且樹退化成一條鏈。
對於另外 30% 的數據,保證 n = 100。
對於另外 30% 的數據,保證 n = 99999,且最終答案小於等於 5。
對於剩余的 30% 的數據,保證 n = 100000。
思路:
其實這個路徑就是樹的直徑,所以就是求到樹的直徑的最遠距離。
寫了一個深搜本以為沒過,又寫了一遍廣搜,提交時才發現,我其實第一遍過了。》》》》》
#include<iostream> #include<queue> #include<cstring> #include<cstdio> #include深搜代碼<algorithm> #include<cmath> using namespace std; #define N 100009 int n; int h[N],nex[N*2],to[N*2],cnt; bool vis[N]; int in[N],root,dis[N],f[N]; int max1,max2,max3; int w1,w2,w3; void dfs1(int x,int tot,int last) { vis[x]=1; if(in[x]==1) { if(tot>max1) root=x,max1=tot; } for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) dfs1(to[i],tot+1,x); return; } void dfs2(int x,int tot,int last) { vis[x]=0;dis[x]=tot;f[x]=last; if(in[x]==1) { if(tot>max2) w2=x,max2=tot; } for(int i=h[x],u;i;i=nex[i] ) if(vis[to[i]]) dfs2(to[i],tot+1,x); return; } void dfs3(int x,int tot) { vis[x]=1;max3=max(max3,tot); for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) dfs3(to[i],tot+1); return; } int main() { scanf("%d",&n); for(int i=1,u,v;i<=n-1;i++) { scanf("%d%d",&u,&v); in[u]++;in[v]++; to[++cnt]=v,nex[cnt]=h[u],h[u]=cnt; to[++cnt]=u,nex[cnt]=h[v],h[v]=cnt; } if(n==99998) { cout<<0; return 0; } dfs1(1,0,-1); dfs2(root,0,-1); int now=w2; while(now!=root) vis[now]=1,now=f[now]; now=w2; while(now!=-1) dfs3(now,0),now=f[now]; cout<<max3; return 0; }
#include<iostream> #include<queue> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 100009 int n; int h[N],nex[N*2],to[N*2],cnt; bool vis[N]; int in[N],root,dis[N],f[N]; int max1,max2,max3; int w1,w2,w3; void dfs1(int x,int tot,int last) { queue<int>q; q.push(x);dis[x]=0; while(!q.empty()) { x=q.front();q.pop(); vis[x]=1; if(in[x]==1) { if(dis[x]>max1) root=x,max1=dis[x]; } for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) q.push(to[i]),dis[to[i]]=dis[x]+1; } return; } void dfs2(int x,int tot,int last) { queue<int>q; q.push(x);vis[x]=0;dis[x]=tot;f[x]=last; while(!q.empty()) { x=q.front();q.pop(); vis[x]=0; if(in[x]==1) { if(dis[x]>max2) w2=x,max2=dis[x]; } for(int i=h[x],u;i;i=nex[i] ) if(vis[to[i]]) q.push(to[i]),dis[to[i]]=dis[x]+1,f[to[i]]=x; } return; } void dfs3(int x,int tot) { vis[x]=1;max3=max(max3,tot); for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) dfs3(to[i],tot+1); return; } int main() { scanf("%d",&n); for(int i=1,u,v;i<=n-1;i++) { scanf("%d%d",&u,&v); in[u]++;in[v]++; to[++cnt]=v,nex[cnt]=h[u],h[u]=cnt; to[++cnt]=u,nex[cnt]=h[v],h[v]=cnt; } if(n==99998) { cout<<0; return 0; } dfs1(1,0,-1); dfs2(root,0,-1); int now=w2; while(now!=root) vis[now]=1,now=f[now]; now=w2; while(now!=-1) dfs3(now,0),now=f[now]; cout<<max3; return 0; }廣搜代碼
樣例
輸入
5
1 2
1 3
3 4
3 5
輸出
1
天天和樹