第一眼感觉像贪心,但是仔细想了想显然不行。
那么考虑dp,f[i][j]表示i这个节点染成j色后,以它为根的子树满足要求,需要染多少个点
j色的话……不包含无色,后面再讲
然后这是一棵无根树?怎么办?
反正也无所谓……你随便拎个非叶子节点当根就可以了,比如说假装是n+1
然后我们考虑转移
son[x]表示x的其中一个子节点
f[x][0]+=min(f[son[x]][0]-1,f[son[x]][1])
f[x][1]+=min(f[son[x]][0],f[son[x]][1]-1)
应该很显然
然后就可以做了
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <cstring>
#include <ctime>
#include <vector>
#define inf 1e9
#define ll long long
#define N 1020
#define y1 orzzyy
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Dow(i,j,k) for(int i=k;i>=j;i--)
using namespace std;
inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; }
inline void write(ll x){ if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10); putchar(x%10+'0'); }
inline void writeln(ll x){write(x);puts("");}
int poi[50001],nxt[50001],head[50001],dp[50001][2];
int col[50001],n,m,x,y,cnt;
inline void add(int x,int y){poi[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;}
inline void dfs(int x,int fa)
{
dp[x][0]=dp[x][1]=1;
if(x<=n)
{
dp[x][0]=dp[x][1]=inf;
dp[x][col[x]]=1;
}
for(int i=head[x];i;i=nxt[i])
{
if(poi[i]==fa) continue;
dfs(poi[i],x);
dp[x][0]+=min(dp[poi[i]][0]-1,dp[poi[i]][1]);
dp[x][1]+=min(dp[poi[i]][0],dp[poi[i]][1]-1);
}
}
int main()
{
m=read();n=read();
For(i,1,n) col[i]=read();
For(i,1,m-1)
x=read(),y=read(),add(x,y),add(y,x);
dfs(n+1,-1);
writeln(min(dp[n+1][0],dp[n+1][1]));
}