题意:
给予你一棵n个节点的树,每一条边有一个容量,你选择一个节点当根,求从根节点到叶子节点的流量的最大值。
思路:
树状dp+换根:
flow[i]为以i为子树i到子树叶子节点的流量最大值。
ans[i]表示以i为根节点时的答案。
flow[u]= min(flow[v],cost(u,v))(v为u的子节点)。
换根:
ans[v]+=min(cost(u,v),ans[u]-min(cost(u,v),flow[v]));(为了节约空间,ans和flow可以共用一个数组)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 998244353
int n;
struct w
{
int to, cost;
}w[200005], w1;
vector<struct w> g[200005];
int flow[300005];
int dfs(int v,int f)
{
if(g[v].size()==1&&f!=-1)
{
flow[v]=g[v][0].cost;
return flow[v];
}
int z=0;
for(int i=0; i<g[v].size(); i++)
{
if(g[v][i].to==f)
{
continue;
}
z=z+min(dfs(g[v][i].to,v),g[v][i].cost);
}
flow[v]=z;
return z;
}
void dfs1(int v,int f)
{
if(g[v].size()==1&&f!=-1)
{
return ;
}
for(int i=0; i<g[v].size(); i++)
{
if(g[v][i].to==f)
{
continue;
}
flow[g[v][i].to]+=min(g[v][i].cost,flow[v]-min(g[v][i].cost,flow[g[v][i].to]));
dfs1(g[v][i].to,v);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
fill(flow,flow+300005,inf);
scanf("%d",&n);
for(int i=0; i<n-1; i++)
{
int s, e, cost;
scanf("%d %d %d",&s,&e,&cost);
w1.cost=cost;
w1.to=e;
g[s].push_back(w1);
w1.to=s;
g[e].push_back(w1);
}
dfs(1,-1);
dfs1(1,-1);
int ma=-1;
for(int i=1; i<=n; i++)
{
ma=max(ma,flow[i]);
}
printf("%d\n",ma);
for(int i=1;i<=n;i++)
{
g[i].clear();
}
}
return 0;
}

京公网安备 11010502036488号