poj3585树最大流——换根法

Posted Zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3585树最大流——换根法相关的知识,希望对你有一定的参考价值。

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

二次扫描与换根法,一次dfs求出以某个节点为根的相关值,再dfs遍历一遍树,根据之前的值换根取最大值为答案。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,head[200005],ct,d[200005],f[200005],deg[200005],ans,t;
bool vis[200005];
struct N{
    int to,next,w;
}edge[400005];
void add(int x,int y,int z)
{
    ct++;
    edge[ct].to=y;
    edge[ct].next=head[x];
    edge[ct].w=z;
    head[x]=ct;
}
void dp(int x)
{
    vis[x]=1;
    for(int i=head[x];i;i=edge[i].next)
    {
        int u=edge[i].to;
        if(vis[u])continue;
        dp(u);
        if(deg[u]==1)d[x]+=edge[i].w;
        else d[x]+=min(d[u],edge[i].w);
    }
}
void dfs(int pre,int w,int x)
{
    vis[x]=1;
    if(deg[pre]==1)f[x]=d[x]+w;
    else f[x]=d[x]+min(f[pre]-min(d[x],w),w);
    ans=max(ans,f[x]);
    for(int i=head[x];i;i=edge[i].next)
    {
        int u=edge[i].to;
        if(vis[u])continue;
        dfs(x,edge[i].w,u);
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(deg,0,sizeof deg);
        memset(f,0,sizeof f);
        memset(d,0,sizeof d);
        memset(head,0,sizeof head);
        memset(vis,0,sizeof vis);
        ans=0;ct=0;
        scanf("%d",&n);
        int a,b,c;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
            deg[a]++;deg[b]++;
        }
        dp(1);
        f[1]=d[1];
        memset(vis,0,sizeof vis);
        dfs(0,0,1);
        printf("%d\n",ans);
    }
    return 0;
}

 

以上是关于poj3585树最大流——换根法的主要内容,如果未能解决你的问题,请参考以下文章

POJ3585 Accumulation Degree(二次扫描与换根法)

POJ3585 Accumulation Degree 树形dp

[POJ 3585] Accumulation Degree

[POJ3585]Accumulation Degree

poj3585 Accumulation Degree(换根dp)

POJ 3585Accumulation Degree