图的直径和树的直径zoj3172
树的直径的证明:
结论:s-t是树的直径,即树上最长的路。则一共满足从任意一点u出发,搜索到的最远的点一定是s或者t。找到s或者t,从s或者t出发搜索即可找到树的直径。
证明:
①如果u是s-t路径上的一个点,那么搜到的一共是s或者t了,否则s-t就不是最长路径了。dis(u,T) >dis(u,s) 且dis(u,T)>dis(u,t) 则最长路不是s-t了,与假设矛盾。
②如果u不是s-t路径上的点,假如u走到了s-t路径上的一点,那么接下来的路径肯定都在s-t上了,而且终点为s或t,在1中已经证明过了
所以现在又有两种情况了:
1:u走到了s-t路径上的某点,假设为X,最后肯定走到某个端点,假设是t ,则路径总长度为dis(u,X)+dis(X,t)
2:u走到最远点的路径u-T与s-t无交点,则dis(u-T) >dis(u,X)+dis(X,t);显然,如果这个式子成立,
则dis(u,T)+dis(s,X)-dis(u,X)>dis(s,X)+dis(X,t)=dis(s,t)最长路不是s-t矛盾
题目连接:http://acm.zju.edu.cn/na_public/showProblem.do?problemCode=3172
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 const int N=1005; 7 int map[N][N]; 8 int vis[N]; 9 int n,m; 10 int depth,ind; 11 void dfs(int count,int u){ 12 int i,j; 13 vis[u]=1; 14 if(depth<count){ 15 depth=count; 16 ind=u; 17 } 18 for(i=0;i<n;i++){ 19 if(map[u][i]&&!vis[i]) 20 dfs(count+1,i); 21 } 22 return ; 23 } 24 int main(){ 25 int i,j; 26 int u,v; 27 while(scanf("%d%d",&n,&m)!=EOF){ 28 memset(map,0,sizeof(map)); 29 memset(vis,0,sizeof(vis)); 30 for(i=0;i<m;i++) 31 scanf("%d%d",&u,&v), 32 map[u][v]=map[v][u]=1; 33 depth=1; 34 dfs(1,0); 35 memset(vis,0,sizeof(vis)); 36 dfs(1,ind); 37 if(depth<7) puts("Impossible"); 38 else printf("%d\n",depth); 39 } 40 return 0; 41 }