• hdu 4679 树状dp


    思路:我们其实只需要枚举每条边,求得最小值就行了。

    先dfs算出每个节点作为根时,其子树的最长路径,以及进过该节点的最长,次长,第三长路径。

    然后在次dfs枚举求出切断某条边,求出这条边的两个端点为子树根,其子树的最长路径。b就是其中较大的。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #define Maxn 200010
    using namespace std;
    int road[Maxn],Max[Maxn],lMax[Maxn],vi[Maxn],e,head[Maxn],dis[Maxn],ldis[Maxn],pr,ans,sMax[Maxn],lroad[Maxn];
    struct Edge{
        int u,v,val,id,next;
    }edge[Maxn*4];
    void init()
    {
        memset(road,0,sizeof(road));
        memset(Max,0,sizeof(Max));
        memset(lMax,0,sizeof(lMax));
        memset(vi,0,sizeof(vi));
        memset(dis,0,sizeof(dis));
        memset(ldis,0,sizeof(ldis));
        memset(head,-1,sizeof(head));
        memset(sMax,0,sizeof(sMax));
        memset(lroad,0,sizeof(lroad));
        e=0;
    }
    void add(int u,int v,int val,int id)
    {
        edge[e].u=u,edge[e].v=v,edge[e].val=val,edge[e].id=id,edge[e].next=head[u],head[u]=e++;
        edge[e].u=v,edge[e].v=u,edge[e].val=val,edge[e].id=id,edge[e].next=head[v],head[v]=e++;
    }
    void dfs(int u)
    {
        int i,v;
        vi[u]=1;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(vi[v]) continue;
            dfs(v);
            if(Max[v]+1>Max[u])
            {
                sMax[u]=lMax[u];
                lroad[u]=road[u];
                lMax[u]=Max[u];
                Max[u]=Max[v]+1;
                road[u]=v;
            }
            else
            if(Max[v]+1>lMax[u])
            {
                sMax[u]=lMax[u];
                lMax[u]=Max[v]+1;
                lroad[u]=v;
            }
            dis[u]=max(dis[u],Max[u]+lMax[u]);
            dis[u]=max(dis[u],dis[v]);
        }
    }
    void predfs(int u,int d,int pre,int fa)
    {
        int i,v;
        vi[u]=1;
        int now=0;
        int a,b=0;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(vi[v]) continue;
            a=edge[i].val;
            now=pre;
            if(road[u]==v)
            {
                now=max(d+lMax[u],now);
                now=max(lMax[u]+sMax[u],now);
                b=max(now,dis[v]);
                if(a*b<=pr)
                {
                    if(a*b==pr)
                    {
                        if(edge[i].id<ans)
                        ans=edge[i].id;
                    }
                    else
                    pr=a*b,ans=edge[i].id;
                }
                predfs(v,max(d,lMax[u])+1,now,u);
            }
            else
            if(lroad[u]==v)
            {
                now=max(d+Max[u],now);
                now=max(Max[u]+sMax[u],now);
                b=max(now,dis[v]);
                if(a*b<=pr)
                {
                    if(a*b==pr)
                    {
                        if(edge[i].id<ans)
                        ans=edge[i].id;
                    }
                    else
                    pr=a*b,ans=edge[i].id;
                }
                predfs(v,max(d,Max[u])+1,now,u);
            }
            else
            {
                now=max(d+Max[u],now);
                now=max(Max[u]+lMax[u],now);
                b=max(now,dis[v]);
                if(a*b<=pr)
                {
                    if(a*b==pr)
                    {
                        if(edge[i].id<ans)
                        ans=edge[i].id;
                    }
                    else
                    pr=a*b,ans=edge[i].id;
                }
                predfs(v,max(d,Max[u])+1,now,u);
            }
        }
    }
    int main()
    {
        int n,i,j,m,t,u,v,w,Case=0;
        scanf("%d",&t);
        while(t--)
        {
            init();
            scanf("%d",&n);
            for(i=1;i<=n-1;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w,i);
            }
            int a,b;
            dfs(1);
            memset(vi,0,sizeof(vi));
            pr=2000000000;
            ans=10000000;
            predfs(1,0,0,0);
            printf("Case #%d: %d
    ",++Case,ans);
        }
        return 0;
    }
  • 相关阅读:
    Tarjan专题
    Catalan数
    状压DP
    威尔逊定理证明:
    【fzoj 2376】「POJ2503」Babelfish
    Android 源码
    Android实现推送方式解决方案
    Android apk 签名
    圆角的实现
    Android 资源
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3262308.html
Copyright © 2020-2023  润新知