zoukankan      html  css  js  c++  java
  • BZOJ3246 IOI2013Dreaming

      如果将森林里每棵树都各自看做一个点,那么最后所连成的树应该是一颗菊花,否则将叶子节点父亲改为根不会更劣。

      对于每个点所代表的树,其和根节点相连的点应该是到其他点距离最大值最小的点。这个点显然是直径的中点。而距离最大值就可以作为点的权值了。

      显然根节点应该是权值最大的。这样连完后讨论一下答案即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 500010
    #define inf 1000000000
    int n,m,l,p[N],deep[N],fa[N],value[N],cnt=0,t=0,ans;
    bool flag[N];
    struct data{int to,nxt,len;
    }edge[N<<1];
    void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
    int dfs1(int k)
    {
        int mx=k;flag[k]=1;
        for (int i=p[k];i;i=edge[i].nxt)
        if (!flag[edge[i].to])
        {
            deep[edge[i].to]=deep[k]+edge[i].len;
            int x=dfs1(edge[i].to);
            if (deep[x]>deep[mx]) mx=x;
        }
        return mx;
    }
    int dfs2(int k)
    {
        int mx=k;
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=fa[k])
        {
            fa[edge[i].to]=k;
            deep[edge[i].to]=deep[k]+edge[i].len;
            int x=dfs2(edge[i].to);
            if (deep[x]>deep[mx]) mx=x;
        }
        return mx;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3246.in","r",stdin);
        freopen("bzoj3246.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),l=read();
        for (int i=1;i<=m;i++)
        {
            int x=read()+1,y=read()+1,z=read();
            addedge(x,y,z),addedge(y,x,z);
        }
        for (int i=1;i<=n;i++)
        if (!flag[i])
        {
            deep[i]=0;int root=dfs1(i);
            deep[root]=0;int x=dfs2(root);
            value[++cnt]=inf;ans=max(ans,deep[x]);
            for (int y=x;y;y=fa[y])
            value[cnt]=min(value[cnt],max(deep[x]-deep[y],deep[y]));
        }
        sort(value+1,value+cnt+1);reverse(value+1,value+cnt+1);value[cnt+1]=value[cnt+2]=-inf;
        cout<<max(ans,max(value[1]+value[2]+l,value[2]+value[3]+(l<<1)));
        return 0;
    }
  • 相关阅读:
    poj 3616 Milking Time
    poj 3176 Cow Bowling
    poj 2229 Sumsets
    poj 2385 Apple Catching
    poj 3280 Cheapest Palindrome
    hdu 1530 Maximum Clique
    hdu 1102 Constructing Roads
    codeforces 592B The Monster and the Squirrel
    CDOJ 1221 Ancient Go
    hdu 1151 Air Raid(二分图最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/Gloid/p/9680064.html
Copyright © 2011-2022 走看看