Accumulation Degree POJ - 3585 (树形dp)(二次扫描和换根法)

Trees are an important component of the natural landscape because of their prevention of erosion and the provision of a specific ather-sheltered ecosystem in and under their foliage. Trees have also been found to play an important role in producing oxygen and reducing carbon dioxide in the atmosphere, as well as moderating ground temperatures. They are also significant elements in landscaping and agriculture, both for their aesthetic appeal and their orchard crops (such as apples). Wood from trees is a common building material.

Trees also play an intimate role in many of the world’s mythologies. Many scholars are interested in finding peculiar properties about trees, such as the center of a tree, tree counting, tree coloring. A(x) is one of such properties.

A(x) (accumulation degree of node x) is defined as follows:

1.Each edge of the tree has an positive capacity.
2.The nodes with degree of one in the tree are named terminals.
3.The flow of each edge can’t exceed its capacity.
4.A(x) is the maximal flow that node x can flow to other terminal nodes.
Since it may be hard to understand the definition, an example is showed below:
这里写图片描述

A(1)=11+5+8=24
Details: 1->2 11
  1->4->3 5
  1->4->5 8(since 1->4 has capacity of 13)
A(2)=5+6=11
Details: 2->1->4->3 5
  2->1->4->5 6
A(3)=5
Details: 3->4->5 5
A(4)=11+5+10=26
Details: 4->1->2 11
  4->3 5
  4->5 10
A(5)=10
Details: 5->4->1->2 10
The accumulation degree of a tree is the maximal accumulation degree among its nodes. Here your task is to find the accumulation degree of the given trees.

Input
The first line of the input is an integer T which indicates the number of test cases. The first line of each test case is a positive integer n. Each of the following n - 1 lines contains three integers x, y, z separated by spaces, representing there is an edge between node x and node y, and the capacity of the edge is z. Nodes are numbered from 1 to n.
All the elements are nonnegative integers no more than 200000. You may assume that the test data are all tree metrics.

Output
For each test case, output the result on a single line.
 

Sample Input
1
5
1 2 11
1 4 13
3 4 5
4 5 10
Sample Output
26
题意:找一个点使得,使得从这个点出发作为源点,发出的流量最大,输出这个最大的流量。
思路:以前的树规都是定点的,就是我们确定了根,或者说选择哪个点作为根都可以,但是这个题就是不一样了,
D[x] D [ x ] 为以x为根的子树中,把x作为源点,从x发出的流量的最大值,这个很用dfs扫描一次可以得出。
转移方程:

D[x]=yson(x)degree[y]==1?c(x,y):min(D[y],c(x,y)) D [ x ] = ∑ y ∈ s o n ( x ) d e g r e e [ y ] == 1 ? c ( x , y ) : min ( D [ y ] , c ( x , y ) )

F[x] F [ x ] 为以x作为整棵树的根是所求的答案,也只要dfs在扫描一次。
易知: D[root]==F[root] D [ r o o t ] == F [ r o o t ]
转移过程:
F[y]=D[y]+degree[x]==1?c(x,y):min(F[x]min(D[y],c(x,y)),c(x,y)) F [ y ] = D [ y ] + d e g r e e [ x ] == 1 ? c ( x , y ) : min ( F [ x ] − min ( D [ y ] , c ( x , y ) ) , c ( x , y ) )

所以二次扫描的名字由此得来.也的确是逻辑上把根换了。
代码:

#include<iostream>
#include<cstdio>
#include<stack>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#define maxx 200005
using namespace std;
int head[maxx],to[maxx<<1],w[maxx<<1],_next[maxx<<1];
int d[maxx];
int cnt=0;
int deg[maxx];
void addEdge(int x,int y,int _w)
{
    to[++cnt]=y,w[cnt]=_w,_next[cnt]=head[x],head[x]=cnt;
    to[++cnt]=x,w[cnt]=_w,_next[cnt]=head[y],head[y]=cnt;
}
int n;
void dfs1(int root,int fa)
{
    d[root]=0;
    for(int i=head[root];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)
            continue;
        dfs1(v,root);
        if(deg[v]==1)
            d[root]+=w[i];
        else
            d[root]+=min(w[i],d[v]);
    }
}
int f[maxx];
void dfs2(int root,int fa)
{
    for(int i=head[root];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)
            continue;
        if(deg[root]==1)
            f[v]=d[v]+w[i];
        else
            f[v]=d[v]+min(f[root]-min(w[i],d[v]),w[i]);
        dfs2(v,root);
    }
}
void init()
{
    memset(head,0,sizeof(head));
    memset(f,0,sizeof(f));
    memset(deg,0,sizeof(deg));
    cnt=0;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        int x,y,w;
        init();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            deg[x]++;
            deg[y]++;
            addEdge(x,y,w);
        }
        if(n==0||n==1)
        {
            cout<<0<<endl;
            continue;
        }
        int root=1;
        dfs1(root,0);
        f[root]=d[root];
        dfs2(root,0);
        int ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,f[i]);
        cout<<ans<<endl;
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值