找学生——(树的直径)
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 }
以上是关于找学生——(树的直径)的主要内容,如果未能解决你的问题,请参考以下文章