Accumulation Degree

题目链接South Central China 2008 Accumulation Degree

Description

(给你一棵有n个结点的树,每一条边连接u_i和v_i)

(流量为w_i,你需要找出一个结点最为root,并且求出从root出发到其他所有叶子结点的流量最大值)

(数据范围1leq nleq 200000,并且sum n leq200000)

Solution

(如果你一来就想到网络流,说明你网络流没学好,树形dp相关的也没学好(笑))

(我们要求出所有root中的最大值,毫无疑问肯定是要对每个结点都求一次的)

(关键在于思考,如果对每一个点作为root去dfs跑他的子树,肯定超时。那么有没有什么方法状态转移)

(在处理转移之前我们先维护一个root的最大流量,我们默认root为结点1,然后对他跑个dfs维护出flow[i])

(flow[i]表示当前结点i所有子树流到流向他的值)

(转移公式 sum_{所有子结点i} flow[p]+= min(w,flow[i]) 注:w为子结点到父节点的流量值,min是限流)

无标题

(在处理好以1为根结点的流量数组flow[]之后,我们来考虑向他的子结点转移)

(观察上面这副图,假设当前结点为u,子结点为v,设某点的流量为f[i].)

(则当前结点的最大流量 f[u] = x + min(y,z);)

(其子结点的最大流量为f[v] = z+min(x,y);)

(我们已知flow[u] = sum_{所有子结点i}flow[i])

(那么f[u]-min(flow[v],w)就表示u子结点v以外子结点的流量贡献,也就是上图的x)

(而子结点flow[v]即表示为上图的z,同时已知y即为w_{u->v})

(所以可以得到f[v]=z+min(x,y)=flow[v]+min(f[u]-min(flow[v],w),w))

(这样转移方程也就出来了)

Code

#include<bits/stdc++.h>
typedef long long ll;
#define IOS ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
const int maxn = 200010;
const int inf = 0x3f3f3f3f;
//思路:从每一个叶子结点跑,然后维护出到当前点最小的值,作为该节点对叶子结点的贡献值
struct node{
    int v; int w;
};
int deg[maxn];
int sum[maxn];
int sum1[maxn];
vector<node>E[maxn];
void dfs(int p,int fa){
    for(int i=0;i<(int)E[p].size();i++){
        int v = E[p][i].v; int w = E[p][i].w;
        if(v!=fa){
            dfs(v,p);
            if(deg[v] == 1){
                sum[p] += w;
            }else{
                sum[p] += min(w,sum[v]); 
            }
        }
    }
    return ;
}
void dfs1(int p,int fa){
    for(int i=0;i<(int)E[p].size();i++){
        int v = E[p][i].v; int w = E[p][i].w;
        if(v!=fa){
            if(deg[p] == 1){
                sum1[v] = w;
            }else{
                sum1[v] = sum[v] + min((sum1[p]- min(sum[v],w)),w);
            }
            dfs1(v,p);
        }
    }
}
int main(){
    IOS
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) {
        	E[i].clear(),deg[i]=0;
        	sum1[i] = sum[i] = 0;
		}
        for(int i=1;i<=n-1;i++){
            int u,v; int w;
            cin>>u>>v>>w;
            E[u].push_back((node){v,w});
            E[v].push_back((node){u,w});
            deg[u]++; deg[v]++;
        }
        dfs(1,0);
        sum1[1] = sum[1];
        dfs1(1,0);
        int ans = -inf;
        for(int i=1;i<=n;i++){
            ans = max(ans,sum1[i]);
        }
        cout<<ans<<endl;
    }
}
原文地址:https://www.cnblogs.com/Tianwell/p/12724829.html