推荐的相关题目显示
题目描述
给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根、内部结点和叶子均可)着以黑色或白色。你的着色方案应该保证根结点到每个叶子的简单路径上都至少包含一个有色结点(哪怕是这个叶子本身)。 对于每个叶结点u,定义c[u]为从根结点从U的简单路径上最后一个有色结点的颜色。给出每个c[u]的值,设计着色方案,使得着色结点的个数尽量少。
输入输出格式
输入格式:
第一行包含两个正整数m, n,其中n是叶子的个数,m是结点总数。结点编号为1,2,...,m,其中编号1,2,... ,n是叶子。以下n行每行一个0或1的整数(0表示黑色,1表示白色),依次为c[1],c[2],...,c[n]。以下m-1行每行两个整数a,b(1<=a < b <= m),表示结点a和b 有边相连。
输出格式:
仅一个数,即着色结点数的最小值。
输入输出样例
说明
M<=10000
N<=5021
这是一道语文题
读懂题其实菜的一批
上代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n,m,c[10500],dp[10500][3],to[20500],nxt[20500],tot,fir[10050]; void ade(int u,int v){ to[++tot]=v; nxt[tot]=fir[u]; fir[u]=tot; } void TREE_DP(int x,int fa){ if(x<=m){ dp[x][0]=9999999; dp[x][c[x]+1]=1; dp[x][2-c[x]]=9999999; return; } dp[x][0]=0; dp[x][1]=1; dp[x][2]=1; for(int k=fir[x];k;k=nxt[k]){ if(to[k]!=fa){ TREE_DP(to[k],x); dp[x][0]+=min(dp[to[k]][1],min(dp[to[k]][0],dp[to[k]][2])); dp[x][1]+=min(dp[to[k]][1]-1,min(dp[to[k]][2],dp[to[k]][0])); dp[x][2]+=min(dp[to[k]][1],min(dp[to[k]][2]-1,dp[to[k]][0])); } } } int main(){ scanf("%d%d",&n,&m); rep(i,1,m) scanf("%d",&c[i]); rep(i,1,n-1){ int x,y; scanf("%d%d",&x,&y); ade(x,y);ade(y,x); } TREE_DP(m+1,0); printf("%d",min(min(dp[m+1][1],dp[m+1][0]),dp[m+1][2])); return 0; }