#include<cstdio>
#include<cstring>
#include<algorithm>
#define en '\n'
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int N=2e5+5;
struct Edge{int to,len,nex;}edge[N<<1];
int head[N],tot;
void add(int from,int to,int len){
edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
edge[++tot]=(Edge){from,len,head[to]};head[to]=tot;
}
int dp[N][2],in[N];//dp[x][0]:x流向子树的最大流量 dp[x][1]:x流向整棵树的最大流量
void dfs1(int x,int fa){
dp[x][0]=0;
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to,len=edge[i].len;
if(y==fa) continue;
dfs1(y,x);
if(in[y]==1) {dp[x][0]+=len;continue;}
dp[x][0]+=min(len,dp[y][0]);
}
}
void dfs2(int x,int fa){
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to,len=edge[i].len;
if(y==fa) continue;
if(in[x]==1) dp[y][1]=dp[y][0]+len;
else dp[y][1]=dp[y][0]+min(len,dp[x][1]-min(dp[y][0],len));
dfs2(y,x);
}
}
int main(){
int T;scanf("%d",&T);
while(T--){
m(head,0),tot=0,m(in,0);
int n;scanf("%d",&n);
for(int i=1;i<=n-1;++i){
int x,y,w;scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
++in[x],++in[y];
}
dfs1(1,1),dp[1][1]=dp[1][0],dfs2(1,1);
int ans=0;
for(int i=1;i<=n;++i) ans=max(ans,dp[i][1]);
printf("%d\n",ans);
}
}
POJ3585(Accumulation Degree 换根dp模板 所有点到所有点的容量)
最新推荐文章于 2021-07-03 23:52:30 发布
本文深入探讨了图论中的最大流算法,通过一个具体的题目示例,详细讲解了如何利用深度优先搜索(DFS)来求解从源点到汇点的最大流。文章首先介绍了数据结构的设计,包括边的定义、邻接表的使用以及动态规划状态转移方程的设定。随后,通过递归的深度优先搜索方法,逐步展示了如何更新残余网络,直至找到从源点到汇点的增广路径,从而求得最大流。此外,还讨论了如何处理特殊情况,如节点的流入流出限制,确保算法的正确性和效率。





679

被折叠的 条评论
为什么被折叠?



