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]);
}

浙公网安备 33010602011771号