AW287 积蓄程度

题目地址


易错点:

  • 注意预处理时的边界条件(if(degree[y]==1)D[x]+=e[i].w;else D[x]+=min(D[y],e[i].w);).
  • 笔者由于边数组开了3e5而调试了近半个小时.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=4e5+10,INF=1<<30;
struct Edge{
	int from,to,w,nxt;
}e[MAXN];
int edgeCnt=1,head[MAXN];
void addEdge(int x,int y,int w){
	e[++edgeCnt].from=x;
	e[edgeCnt].to=y;
	e[edgeCnt].w=w;
	e[edgeCnt].nxt=head[x];
	head[x]=edgeCnt;
}
int D[MAXN],degree[MAXN];
bool vis1[MAXN];
int f[MAXN];
void dfs(int x){
	vis1[x]=1;
	for(int i=head[x];i;i=e[i].nxt){
		int y=e[i].to;
		if(vis1[y])continue;
		dfs(y);
		if(degree[y]==1)D[x]+=e[i].w;
		else D[x]+=min(D[y],e[i].w);
	}
}
int ans=-INF;
bool vis2[MAXN];
void dp(int x){
	vis2[x]=1;
	ans=max(ans,f[x]);
	for(int i=head[x];i;i=e[i].nxt){
		int y=e[i].to;
		if(f[y]||vis2[y])continue;
		f[y]=D[y]+min(e[i].w,f[x]-min(e[i].w,D[i]));
		dp(y);
	}
}
int n;
void init(){
	edgeCnt=1;
	ans=-INF;
	for(int i=1;i<=n;i++){
		head[i]=vis1[i]=vis2[i]=degree[i]=f[i]=D[i]=0;
	}
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		init();
		for(int i=1;i<=n-1;i++){
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			addEdge(x,y,z);
			addEdge(y,x,z);
			degree[x]++,degree[y]++;
		}
		dfs(1);
		f[1]=D[1];
		dp(1);
		printf("%d
",ans);
	}
	return 0;
} 
原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680571.html