每日一题 Accumulation Degree换根dp

题目链接

题意:给你一个n个节点的树,每条边有个流量上限。

选择一个节点为根节点,求它流向所有子节点的流量之和,根节点的流量是无限的

做法:设flow[i]为i节点的流量和,

状态方程:flow[i]=∑min(flow[j],edge[i][j])(j是i的儿子)

换根dp一下即可。注意叶子节点要特判

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
vector<pair<int,ll> >G[N];
vector<ll>pre[N];
ll n,flow[N],ans;
void dfs1(int u,int fa)
{
    for(auto now:G[u]){
        int v=now.first;
        ll w=now.second;
        if(v==fa) continue;
        if(G[v].size()==1){
            flow[u]+=w;
        }
        else{
            dfs1(v,u);
            flow[u]+=min(flow[v],w);
        }
    }
}
void dfs2(int u,int fa)
{
    //printf("u:%d fa:%d fl:%lld\n",u,fa,flow[u]);
    ans=max(ans,flow[u]);
    pre[u].push_back(0);
    for(int i=0;i<G[u].size();++i){
        auto now=G[u][i];
        int v=now.first;ll w=now.second;
        pre[u].push_back(pre[u][i]);
        if(G[v].size()==1)pre[u][i+1]+=w;
        else pre[u][i+1]+=min(flow[v],w);
    }
    ll last=0;

    //puts("****");
    for(int i=G[u].size()-1;i>=0;--i){
        auto now=G[u][i];
        int v=now.first;
        ll w=now.second;


        flow[u]=0;
        ll nw=pre[u][i]+last;
        flow[u]=nw;

        if(G[u].size()==1) flow[v]+=w;
        else flow[v]+=min(w,flow[u]);

        if(v!=fa) dfs2(v,u);
        if(G[u].size()==1) last+=w;
        else last+=min(w,flow[u]);
    }
}
void solve()
{
    scanf("%d",&n);
    for(int i=0;i<=n+1;++i){
        G[i].clear();
        pre[i].clear();
        flow[i]=0;
    }
    for(int i=1;i<n;++i){
        int u,v;
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        G[u].push_back(make_pair(v,w));
        G[v].push_back(make_pair(u,w));
        flow[i]=0;
    }
    ans=0;
    dfs1(1,-1);
    //for(int i=1;i<=n;++i) printf("i:%d flow:%lld\n",i,flow[i]);
    dfs2(1,-1);
    printf("%lld\n",ans);
}
int main()
{
	//ios::sync_with_stdio(false);
    //freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int _;cin>>_;while(_--)
	solve();
}
发布了519 篇原创文章 · 获赞 69 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/105517131
今日推荐