找学生——(树的直径)

Posted lour688

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了找学生——(树的直径)相关的知识,希望对你有一定的参考价值。

技术图片

 

 

这道题其实就是一道无根树上树的直径的问题:

技术图片

如图,首先根据上面的做法,用两次BFS求出树的直径,即AB。

那么其实发现在实际上,问题要求max{AB+BC}(BC<AC)或max{AB+AC}(AC<BC),那么这两个式子可以合并成求max{AB+min{BC,AC}}。

只要确定了直径的端点A、B,然后再枚举C点,求得最大值即为答案。

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=200005; 
 8 struct node{
 9     ll to,next,val;
10 }edge[maxn<<1];
11 ll d[maxn],k[maxn],head[maxn],vis[maxn];
12 int n,m,tot;
13 queue<int> q;
14 void add(int u,int v,int w){
15     edge[tot].to=v;
16     edge[tot].next=head[u];
17     edge[tot].val=w;
18     head[u]=tot++;
19 }
20 int BFS(int s){
21     ll maxd=0,Max;
22     memset(d,0,sizeof(d));
23     memset(vis,0,sizeof(vis));
24     while(!q.empty()) q.pop();
25     q.push(s); vis[s]=1;
26     while(!q.empty()){
27         int u=q.front(),v; q.pop();
28         for(int i=head[u];i!=-1;i=edge[i].next){
29             if(vis[v=edge[i].to]) continue;
30             vis[v]=1;
31             d[v]=d[u]+edge[i].val;
32             q.push(v);
33             if(d[v]>maxd){
34                 maxd=d[v];
35                 Max=v;
36             }
37         }
38     }
39     return Max;
40 }
41 int main(){
42 //    freopen("1.in","r",stdin); 
43     memset(head,-1,sizeof(head));
44     scanf("%d%d",&n,&m);
45     for(int i=1;i<=m;i++){
46         ll x,y,z;
47         scanf("%lld%lld%lld",&x,&y,&z);
48         add(x,y,z); add(y,x,z);
49     }
50     int l=BFS(1);//A 
51     int r=BFS(l);//B
52     ll ans=d[r];//直径长度 
53     for(int i=1;i<=n;i++) k[i]=d[i];//k:AC长度 
54     BFS(r);
55     ll M=0;
56     for(int i=1;i<=n;i++) M=max(M,min(d[i],k[i]));//枚举C点 d:BC长度 
57     printf("%lld
",ans+M);
58     return 0;
59 } 

 

以上是关于找学生——(树的直径)的主要内容,如果未能解决你的问题,请参考以下文章

ACM入门之树的直径

51Nod2602 树的直径

树的直径

树的直径

树的直径求法与性质(附例题)

BZOJ 3363 POJ 1985 Cow Marathon 树的直径