码迷,mamicode.com
首页 > 其他好文 > 详细

poj3585树最大流——换根法

时间:2018-03-19 23:34:24      阅读:625      评论:0      收藏:0      [点我收藏+]

标签:turn   int   最大流   col   next   +=   eof   pac   div   

题目: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树最大流——换根法

标签:turn   int   最大流   col   next   +=   eof   pac   div   

原文地址:https://www.cnblogs.com/Zinn/p/8605654.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!