HLG 1477 战争与守卫【树形DP】
题意:
J国和C国爆发了战争,J国派出了很多间谍深入到C国内部,经常在C国的城市之间炸毁道路,阻拦C国的军队,C国为了抓到这些间谍,需要派人在城市进行监视,一个城市只要有一个人监视,那么这个城市的所有的道路也都会被监视到,为了能够尽量多的士兵去前线打仗,监视的士兵要尽可能的少,希望靠你编程求出至少需要多少人能实现对所有城市之间道路的监视。
分析: // dp[i][0] 在 i 节点不放士兵
// dp[i][1] 在 i 节点放士兵
// dp[i][0]+=dp[j][1]
// dp[i][1]+=min(dp[j][0],dp[j][1])
#include<stdio.h> #include<string.h> #define min(a,b)(a)<(b)?(a):(b) int v[1550]; struct node { int to; int next; }q[15001]; int head[1501],dp[1501][2],tot; void add(int s,int u) { q[tot].to=u; q[tot].next=head[s]; head[s]=tot++; } int dfs(int i) { int j,k; dp[i][0]=0; dp[i][1]=1; for(j=head[i];j;j=q[j].next) { k=q[j].to; if(!v[k]) dfs(k); v[k]=1; dp[i][0]+=dp[k][1]; dp[i][1]+=min(dp[k][0],dp[k][1]); } return min(dp[i][0],dp[i][1]); } int main() { int i,m,n,s,w,root; while(scanf("%d",&n)!=EOF) { tot=1; root=-1; memset(head,0,sizeof(head)); memset(v,0,sizeof(v)); for(i=0;i<n;i++) { scanf("%d:(%d)",&s,&m); if(root==-1) root=s; while(m--) { scanf("%d",&w); add(s,w); } } printf("%d\n",dfs(root)); } return 0; }