树的直径

定义

树的直径——就是树中距离最大的两点的距离。

无根树直径的求法

求无根树的直径:

1.利用dp实现,就是求最长链与次长链,可以用两次DFS求得,这里就不详细讨论。

2.利用直径的性质:Step 1.首先任取一点作为根,用DFS找出树中与它距离最远的点,记为点k。

           Step 2.以k为根,再次DFS,找出树中与它距离最远的点,其距离即为直径。

有何理由?详见这里

模版题

下面列出两题:

1.poj1985

非常裸,就是练练手。直接贴代码了。

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 struct node{
 5        int link,dt;
 6        node *next;
 7 }ES[90000],*son[40009];
 8 int m,n,t,s,ans,EC=0;
 9 void tr(int fa,int v,int d)
10 {
11      if (d>ans) ans=d,s=v;
12      for (node *tmp=son[v];tmp;tmp=tmp->next)
13          if (tmp->link!=fa){
14             int u=tmp->link;
15             tr(v,u,d+tmp->dt);
16             }
17 }
18 void addedge(int x,int y,int z)
19 {
20      ES[++EC].next=son[x];
21      son[x]=ES+EC;
22      son[x]->link=y;
23      son[x]->dt=z;
24 }
25 int main()
26 {
27     freopen("poj1985.in","r",stdin);freopen("poj1985.out","w",stdout);
28     while (scanf("%d%d",&n,&m)!=EOF){
29           ans=0;
30           memset(son,0,sizeof(son));
31           EC=0;
32           for (int i=1;i<=m;++i){
33               int x,y,l;
34               scanf("%d%d%d ",&x,&y,&l);
35               char c;
36               scanf("%c",&c);
37               addedge(x,y,l);
38               addedge(y,x,l);
39               }
40           tr(0,1,0);
41           ans=0;
42           tr(0,s,0);
43           printf("%d\n",ans);
44           }
45     fclose(stdin);fclose(stdout);
46 }

2.hdu2196

事实上也是水题。但是要先了解树的直径的性质。

若(s,t)是一条直径,则树中任意一点到s,t的距离的最大值必定是其与树中离他最远的点的距离。

何以如此?

证明非常简单。如下:

记u为树中一点,(s,t)为直径。

假设能够找到一点v使得dis[u][v]>max(dis[u][s],dis[u][t])(不妨设dis[u][s]>dis[u][t]),则dis[u][v]+dis[u][s]>dis[u][s]+dis[u][t]>=dis[s][t]=直径。

矛盾,于是结论成立。

了解了这个性质,这题就很简单了。3遍bfs即可。

View Code
 1 #include <cstdio>
 2 #include <queue>
 3 #include <algorithm>
 4 #include <memory>
 5 using namespace std;
 6 struct node{
 7        int link,dt;
 8        node *next;
 9 }ES[30009],*son[10009];
10 int n,dis[10009],temp[10009],EC=0;
11 bool b[10009];
12 queue<int> q;
13 void addedge(int x,int y,int z)
14 {
15      ES[++EC].next=son[x];
16      son[x]=ES+EC;
17      son[x]->link=y;
18      son[x]->dt=z;
19 }
20 int bfs(int k)
21 {
22      int Max=0;
23      memset(dis,0,sizeof(dis));
24      memset(b,0,sizeof(b));
25      q.push(k);
26      b[k]=1;
27      for (;!q.empty();q.pop()){
28          int x=q.front();
29          for (node *tmp=son[x];tmp;tmp=tmp->next)
30              if (!b[tmp->link]){
31                 int u=tmp->link;
32                 dis[u]=dis[x]+tmp->dt;
33                 q.push(u);
34                 b[u]=1;
35                 if (dis[u]>Max){
36                    Max=dis[u];
37                    k=u;
38                    }
39                 }
40          }
41      return k;
42 }
43 int main()
44 {
45 #ifndef ONLINE_JUDGE
46     freopen("Computer.in","r",stdin);freopen("Computer.out","w",stdout);
47 #endif
48     while (scanf("%d",&n)!=EOF){
49           memset(son,0,sizeof(son));
50           EC=0;
51           for (int i=1;i<n;++i){
52               int x,y;
53               scanf("%d%d",&x,&y);
54               addedge(x,i+1,y);
55               addedge(i+1,x,y);
56               }   
57           int s=bfs(1); 
58           s=bfs(s);
59           for (int i=1;i<=n;++i) temp[i]=dis[i];
60           bfs(s);
61           for (int i=1;i<=n;++i) printf("%d\n",max(temp[i],dis[i]));
62           }
63 #ifndef ONLINE_JUDGE
64     fclose(stdin);fclose(stdout);
65 #endif
66 }
原文地址:https://www.cnblogs.com/lazycal/p/2637113.html