题目
有一个树形的水系,由 N-1 条河道和 N 个交叉点组成。
我们可以把交叉点看作树中的节点,编号为 1~N,河道则看作树中的无向边。
每条河道都有一个容量,连接 x 与 y 的河道的容量记为 c(x,y)。
河道中单位时间流过的水量不能超过河道的容量。
有一个节点是整个水系的发源地,可以源源不断地流出水,我们称之为源点。
除了源点之外,树中所有度数为 1 的节点都是入海口,可以吸收无限多的水,我们称之为汇点。
也就是说,水系中的水从源点出发,沿着每条河道,最终流向各个汇点。
在整个水系稳定时,每条河道中的水都以单位时间固定的水量流向固定的方向。
除源点和汇点之外,其余各点不贮存水,也就是流入该点的河道水量之和等于从该点流出的河道水量之和。
整个水系的流量就定义为源点单位时间发出的水量。
在流量不超过河道容量的前提下,求哪个点作为源点时,整个水系的流量最大,输出这个最大值。
输入格式
输入第一行包含整数T,表示共有T组测试数据。
每组测试数据,第一行包含整数N。
接下来N-1行,每行包含三个整数x,y,z,表示x,y之间存在河道,且河道容量为z。
节点编号从1开始。
输出格式
每组数据输出一个结果,每个结果占一行。
数据保证结果不超过231−1。
数据范围
N≤2∗105
输入样例:
1
5
1 2 11
1 4 13
3 4 5
4 5 10
输出样例:
26
思路
这道题目有点像最大流,这题我们采用树形dp进行换根,因为他要求可能的最大水流,那么如果我们以每个点为根暴力显然超时,所以我们只需要刚开始以一个点为根求出每个点往下的最大流,然后从上往下在dfs一遍,进行dp换根。
代码实现
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=0;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int ,int> PII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
inline int read() {
char ch=getchar(); int x=0, f=1;
while(ch<'0'||ch>'9') {
if(ch=='-') f = -1;
ch=getchar();
}
while('0'<=ch&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
} return x*f;
}
const int maxn=2e5+5;
vector <PII> G[maxn];
int n;
int ans;
int d[maxn];
int f[maxn];
int deg[maxn];
int dfs_d (int u,int fa) {
if (deg[u]==1) {
d[u]=inf;
return d[u];
}
d[u]=0;
for (auto it:G[u]) {
int j=it.first;
if (j==fa) continue;
d[u]+=min (dfs_d (j,u),it.second);
}
return d[u];
}
void dfs_f (int u,int fa) {
for (auto it:G[u]) {
int j=it.first;
if (j==fa) continue;
if (deg[j]==1) f[j]=min (f[u]-it.second,it.second);
else {
f[j]=d[j]+min (f[u]-min (it.second,d[j]),it.second);
dfs_f (j,u);
}
}
}
int main () {
ios::sync_with_stdio (false);
int t;
cin>>t;
while (t--) {
scanf ("%d",&n);
int temp,flag=0;
rep (i,1,n) G[i].clear ();
MT (deg,0);
rep (i,1,n-1) {
int a,b,c;
a=read (), b=read (),c=read ();
G[a].pb (mp (b,c));
if (!flag) {
temp=c;
flag=1;
}
G[b].pb (mp (a,c));
deg[a]++,deg[b]++;
}
int root=1;
while (root<=n&°[root]==1) root++;
if (root>n) {
cout<<temp<<endl;
continue;
}
dfs_d (root,-1);
f[root]=d[root];
dfs_f (root,-1);
ans=0;
rep (i,1,n) ans=max (ans,f[i]);
printf ("%d
",ans);
}
return 0;
}