图的直径和树的直径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

View Code
 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 }

 

posted @ 2013-04-10 21:33  _sunshine  阅读(256)  评论(0编辑  收藏  举报