一开始想偏了。。。以为可以直接贪心结果不能。
dp[x][0/1]表示x子树的答案,x刷白或黑。
可以发现根节点是一定要刷的,所以选什么作为根都没有影响。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 10050 #define maxe 20050 #define inf 1000000007 using namespace std; int n,k,x,y,c[maxv],g[maxv],nume=1,fath[maxv],dp[maxv][2]; struct edge { int v,nxt; }e[maxe]; void addedge(int u,int v) {e[++nume].v=v;e[nume].nxt=g[u];g[u]=nume;} void dfs1(int x) { if (x<=k) { dp[x][c[x]]=1;dp[x][c[x]^1]=inf; return; } dp[x][0]=dp[x][1]=1; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (v==fath[x]) continue; fath[v]=x;dfs1(v); dp[x][0]+=min(dp[v][0]-1,dp[v][1]); dp[x][1]+=min(dp[v][0],dp[v][1]-1); } } int main() { scanf("%d%d",&n,&k); for (int i=1;i<=k;i++) scanf("%d",&c[i]); for (int i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); addedge(x,y);addedge(y,x); } dfs1(n); printf("%d\n",min(dp[n][0],dp[n][1])); return 0; }