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

 

以上是关于bzoj3124 直径 树论的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3124 直径

Bzoj 3124: [Sdoi2013]直径 题解

bzoj3124: [Sdoi2013]直径

bzoj3124

3124: [Sdoi2013]直径

SDOI2013 R1 Day1