bzoj3124 直径 树论
Posted Loser Of Life
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3124 直径 树论相关的知识,希望对你有一定的参考价值。
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3124
题意:求出带权树直径长度,同时求出直径上有多少条边是所有直径都经过了的。
求直径……很好求啊,两遍$bfs$瞎**乱搞即可……但是第二问就不是那么好解决了……
只能选择%%题解……
题解的思路是:两遍$bfs$的时候,分别记录下来所有最远点。如果最远点只有一个那根本不用说这个点一定在直径上;如果最远点不止一个,那这些最远点会分别出现在不同的直径上,但是,它们的$LCA$一定是在直径上的。那么我们就分别求求两次的$LCA$,最后第二问的答案就是$abs{dep[LCA1]-dep[LCA2]}$。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int maxn=200005; 7 struct node 8 { 9 int from,to,next;long long dis; 10 node(){} 11 node(int u,int v,long long w,int x):from(u),to(v),dis(w),next(x){} 12 }edge[maxn<<1]; 13 int head[maxn],tot; 14 void addedge(int u,int v,long long w) 15 { 16 edge[++tot]=node(u,v,w,head[u]);head[u]=tot; 17 } 18 int n,dep[maxn],pa[maxn],rt[maxn][30];long long dis[maxn]; 19 #include<queue> 20 queue<int>Q; 21 void bfs(int root) 22 { 23 memset(dis,0xff,sizeof(dis));memset(dep,0,sizeof(dep)); 24 dis[root]=0;Q.push(root);pa[root]=-1;dep[root]=1; 25 while(!Q.empty()) 26 { 27 int now=Q.front();Q.pop(); 28 for(int i=head[now];i;i=edge[i].next) 29 { 30 int v=edge[i].to; 31 if(dis[v]>=0)continue; 32 dis[v]=dis[now]+edge[i].dis;dep[v]=dep[now]+1;pa[v]=now;Q.push(v); 33 } 34 } 35 } 36 #include<vector> 37 vector<int>G; 38 void init() 39 { 40 for(int i=1;(1<<i)<=n;i++) 41 for(int j=1;j<=n;j++)rt[j][i]=-1; 42 for(int i=1;i<=n;i++)rt[i][0]=pa[i]; 43 for(int j=1;(1<<j)<=n;j++) 44 for(int i=1;i<=n;i++) 45 if(rt[i][j-1]!=-1)rt[i][j]=rt[rt[i][j-1]][j-1]; 46 } 47 int LCA(int x,int y) 48 { 49 if(dep[x]<dep[y])swap(x,y); 50 for(int i=20;~i;i--) 51 if(dep[x]-(1<<i)>=dep[y])x=rt[x][i]; 52 if(x==y)return x; 53 for(int i=20;~i;i--) 54 if(rt[x][i]!=-1&&rt[x][i]!=rt[y][i])x=rt[x][i],y=rt[y][i]; 55 return pa[x]; 56 } 57 int haha() 58 { 59 scanf("%d",&n); 60 for(int i=1;i<n;i++) 61 { 62 int x,y;long long z;scanf("%d%d%lld",&x,&y,&z); 63 addedge(x,y,z);addedge(y,x,z); 64 } 65 bfs(1);long long ans=0;int pos;init(); 66 for(int i=1;i<=n;i++) 67 { 68 if(dis[i]>ans)ans=dis[i],G.clear(); 69 if(dis[i]==ans)G.push_back(i); 70 } 71 int now=G[0]; 72 for(int i=1;i<G.size();i++)now=LCA(now,G[i]); 73 int lca1=now,root=G[0];bfs(root);ans=0;init();G.clear(); 74 for(int i=1;i<=n;i++) 75 { 76 if(dis[i]>ans)ans=dis[i],G.clear(); 77 if(dis[i]==ans)G.push_back(i); 78 } 79 printf("%lld\n",ans);now=G[0]; 80 for(int i=1;i<G.size();i++)now=LCA(now,G[i]); 81 // cout<<lca1<<" "<<now<<endl; 82 printf("%d\n",abs(dep[lca1]-dep[now])); 83 } 84 int sb=haha(); 85 int main(){;}
以上是关于bzoj3124 直径 树论的主要内容,如果未能解决你的问题,请参考以下文章