题目意思:给出一个无向图,n个顶点,n-1条边。每条边有权值w,表示流量。
流量:本来我实在没理解题目样例的解释,后来问了一位大佬的解,秒懂了.其实边权可以理解成水管的粗细,水能流多少。
比如1->4-3 首先1->4可以通过13的水,由于4->3水管只有5的大小,所以1-4-3只能流出5.
再比如1->4->5 之前1->4->3 已经流出了5 那么1->4->5 剩下还有8,粗细为10的可以全部通过,所以1->4->5流出是8.
题目要求的是,以某个点为根,计算根到所有叶子节点的流量和
最后再取最大值
好了题意应该理解了。。。。
分析:这是一道换根dp题,思路就是换根之后和换根之前的贡献差异,推出转移方程即可。
首先分成2种情况:
第一种换根节点为叶子节点(比较特殊)
如图所示:
第二种换根节点不是叶子节点(常规情况)
如图所示:
这里注意的是,如果用一个数组来存结果,那么中间变动的值不能改变。详细看代码细节。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <cctype>
#include <cmath>
#include <cassert>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=200000+100;
int t;
int n;
int x,y,z;
int head[N],tot;
int isleaf[N];//判断是不是叶子节点
int f[N];//每个节点总贡献
struct Edge
{
int e;
int to;
int w;//权值
}edge[N<<1];
void add_edge(int u,int v,int val)
{
tot++;
edge[tot].e=v;
edge[tot].to=head[u];
edge[tot].w=val;
++isleaf[u];//每次加边的时候,由于我们正反2次加,所以叶子节点最后的isleaf值一定是2
++isleaf[v];
head[u]=tot;
}
void init()
{//初始化函数
memset(head,0,sizeof(head));
tot=0;
for(int i=0;i<N;i++)
{
edge[i].e=0;
edge[i].to=0;
edge[i].w=0;
}
memset(isleaf,0,sizeof(isleaf));
memset(f,0,sizeof(f));
}
void dfs(int u,int fa)
{//第一次dfs,计算从1为根的所有点的流量
for(int i=head[u];i!=0;i=edge[i].to)
{
int v=edge[i].e;
int w=edge[i].w;
if(v==fa)continue;
dfs(v,u);
//如果是叶子节点,直接加上流量,不是叶子节点,和当前权值取最小值即可
if(isleaf[v]==2)f[u]+=w;
else f[u]+=min(f[v],w);
}
}
void dfs2(int u,int fa)
{
for(int i=head[u];i!=0;i=edge[i].to)
{
int v=edge[i].e;
int w=edge[i].w;
if(v==fa)continue;
//把根换做v
if(isleaf[v]==2)f[v]+=w;//叶子节点的时候
else
{
int k=f[u]-min(f[v],w);//用一个临时变量存一下,不能直接改变.
// f[u]-=min(f[v],w);这样写是错的
f[v]+=min(w,k);
}
dfs2(v,u);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,z);
}
// for(int i=1;i<=n;i++)
// {
// if(isleaf[i]==2)
// {
// printf("%d is leap\n",i);
// }
// else
// {
// printf("%d is not leap\n",i);
// }
// }
dfs(1,0);
// for(int i=1;i<=n;i++)
// {
// printf("f[%d]:%d\n",i,f[i]);
// }
// printf("f[1]:%d\n",f[1]);
dfs2(1,0);
// for(int i=1;i<=n;i++)
// {
// printf("f[%d]:%d\n",i,f[i]);
// }
int maxx=-1e9;
for(int i=1;i<=n;i++)
{
maxx=max(maxx,f[i]);
}
printf("%d\n",maxx);
}
return 0;
}

京公网安备 11010502036488号