把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P3931 SAC E#1 - 一道难题 Tree

题面传送门
考虑用树形\(dp\)来解。
则设\(f_i\)为让\(i\)节点的子树的叶子节点被封锁的最小值,那么\(f_i=min(w,\sum\limits_{(i,j)∈E}{f_j})\)
跑一遍\(dfs\)就可以求出答案
时间复杂度\(O(n)\)
代码实现:

#include<cstdio>
#include<cstring>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,dp[100039],h[100039],head,x,y,z;
struct yyy{
	int to,w,z;
}f[200039],tmp;
inline void add(int x,int y,int z){
	f[++head]=(yyy){y,z,h[x]};
	h[x]=head;
}
inline void dfs(int x,int last,int w){
	int cur=h[x],ans=0;
	yyy tmp;
	while(cur!=-1){
		tmp=f[cur];
		if(tmp.to!=last) dfs(tmp.to,x,tmp.w);
		cur=tmp.z;
	}
	cur=h[x];
	while(cur!=-1){
		tmp=f[cur];
		if(tmp.to!=last) ans+=dp[tmp.to];
		cur=tmp.z;
	}
	if(!ans) dp[x]=w;
	else dp[x]=min(ans,w);
	//printf("%d %d %d %d\n",x,w,ans,dp[x]);
}
int main(){
	memset(h,-1,sizeof(h));
	register int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
	dfs(m,0,1e9);
	printf("%d\n",dp[m]);
}
posted @ 2020-04-06 14:34  275307894a  阅读(43)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end