• 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
    ",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
    ",abs(dep[lca1]-dep[now]));
    83 }
    84 int sb=haha();
    85 int main(){;}
    bzoj3124
  • 相关阅读:
    拖动图片浏览的程序(VB6)
    Nod32升级服务器(转)
    看了部电影"蝴蝶效应"
    BackgroundWorker的替代者! (转)
    为什么我爱黑莓8700
    什么是反射(.NET)[转]
    使用VS2008编写了第一个WM5短信发送程序!
    不睡觉果然还是不行。
    关于net2.0里面新出现的类backgroundworker的应用 (转)
    是男人就打5000分!(C#)
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7780483.html
Copyright © 2020-2023  润新知