zoukankan      html  css  js  c++  java
  • POJ3585 Accumulation Degree(二次扫描与换根法)

    题目:http://poj.org/problem?id=3585

    很容易想出暴力。那么就先扫一遍。

    然后得到了指定一个根后每个点的子树值。

    怎么转化利用一下呢?要是能找出当前点的父亲的 “ 不含当前点的其他子树值 ” 就好了。

    发现只需要把父亲的值减去 min ( 当前子树的值,该点与父亲间的边的值 ) 就行了!(因为当初这样加过)

    需要注意一下的是叶节点。赋成INF或边的值都行。

    特别需要注意的是第一次选的根节点在其余时候是叶节点的情况!!!!!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int T,n,xnt,head[200005],rd[200005],x,y,z,yt;
    const int INF=200005;
    long long d[200005],ans;
    struct Node{
        int next,to;
        long long w;
    }edge[400005];
    void add(int x,int y,int z)
    {
        edge[++xnt].next=head[x];
        edge[xnt].to=y;
        edge[xnt].w=z;
        head[x]=xnt;
        rd[x]++;
    }
    void dfs1(int k,int fa)
    {
        if(rd[k]==1&&k!=yt)
        {
            d[k]=INF;
            return;
        }
        for(int i=head[k];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(v==fa)continue;
            dfs1(v,k);
            d[k]+=min(d[v],edge[i].w);
    //        printf("1 k=%d d=%lld
    ",k,d[k]);
        }
    }
    void dfs2(int k,int fa,int u)
    {
        long long r=d[fa]-min(d[k],edge[u].w); 
        if(rd[fa]==1)r=edge[u].w;///////////////当根节点也是叶节点时!很特殊 
        if(rd[k]==1)
        {
            d[k]=min(r,edge[u].w);
            return;
        }
        d[k]+=min(r,edge[u].w);
    //    printf("2 k=%d d=%lld
    ",k,d[k]);
        for(int i=head[k];i;i=edge[i].next)
        {
            if(edge[i].to==fa)continue;
            dfs2(edge[i].to,k,i);
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            memset(head,0,sizeof head);
            memset(d,0,sizeof d);
            memset(rd,0,sizeof rd);
            xnt=0;ans=-1;///////
            scanf("%d",&n);
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);add(y,x,z);
            }
            yt=1;
            dfs1(1,0);
            for(int i=head[1];i;i=edge[i].next)
                dfs2(edge[i].to,1,i);
            for(int i=1;i<=n;i++)ans=max(ans,d[i]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Exchange调整入站SMTP连接超时时间
    使用WSS和SOFS管理集群存储--Storage
    String构造方法和字符集编码转换
    系统类和数学操作类
    JavaSE——数据类型流、内存流、打印流
    JavaSE——装饰设计模式+简单加密解密工程
    JavaSE——装饰设计模式
    JavaSE——装饰流
    JavaSE —— IO
    JavaSE —— IO简介
  • 原文地址:https://www.cnblogs.com/Narh/p/8577505.html
Copyright © 2011-2022 走看看