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;
    }
  • 相关阅读:
    多重背包POJ1276不要求恰好装满 poj1014多重背包恰好装满
    哈理工1053完全背包
    求最小公倍数与最大公约数的函数
    Bus Pass ZOJ 2913 BFS 最大中取最小的
    POJ 3624 charm bracelet 01背包 不要求装满
    HavelHakimi定理(判断一个序列是否可图)
    z0j1008Gnome Tetravex
    ZOJ 1136 Multiple BFS 取模 POJ 1465
    01背包 擎天柱 恰好装满 zjut(浙江工业大学OJ) 1355
    zoj 2412 水田灌溉,求连通分支个数
  • 原文地址:https://www.cnblogs.com/Gloid/p/9680064.html
Copyright © 2011-2022 走看看