一、题目描述:
给你一颗 $n$ 个点的树,每个点的颜色要么是 $W$ ,要么是 $B$ 。满足每个点的度数是奇数。
将这 $n$ 个点同时进行染色,这个点被染成它所连接的点中占多数的颜色。给你染色之后的颜色序列。
求是否存在一种颜色序列,使得染色之后可以变成现在的颜色序列。
如果不存在,输出 $-1$ ;如果存在,输出这个颜色序列。$1\leq n\leq 2\times 10^5$ 。
二、解题思路:
$dfs$ 以随意一个点为根建树。
设染色后的 $i$ 颜色序列为 $c_i$ 。
设染色前的 $i$ 颜色序列为 $ans_i$ 。
我们将 $ans$ 数组初始化为 $-1$ 。
然后暴力统计即可,注意两个点:
$1.\ 当一个点\ i\ 的儿子不需要它时,贪心地将\ ans_i\ 赋值为\ c_{fa}\ 。$
$2.\ 注意根节点只有儿子,没有父亲。$
没什么好讲的,因为本来这个题就不难。
三、完整代码:
1 #include<iostream> 2 #define N 200010 3 using namespace std; 4 string s; 5 int T,n,u1,v1; 6 int c[N],du[N],tot[N],ans[N]; 7 struct EDGE{ 8 int v,nxt; 9 }edge[N*2]; 10 int head[N],cnt; 11 void add(int u,int v) 12 { 13 edge[++cnt].v=v; 14 edge[cnt].nxt=head[u]; 15 head[u]=cnt; 16 } 17 int dfs(int u,int ff) 18 { 19 for(int i=head[u];i!=-1;i=edge[i].nxt) 20 if(edge[i].v!=ff) 21 { 22 if(!dfs(edge[i].v,u)) 23 return 0; 24 if(ans[edge[i].v]==-1) 25 ans[edge[i].v]=c[u]; 26 if(ans[edge[i].v]==c[u]) 27 tot[u]++; 28 } 29 if(tot[u]*2<du[u]) 30 { 31 if(ans[ff]==-1) ans[ff]=c[u]; 32 if(!ff||tot[u]*2+2<du[u]||ans[ff]!=c[u]) 33 return 0; 34 } 35 return 1; 36 } 37 void solve() 38 { 39 cin>>n;cnt=0; 40 for(int i=1;i<=n;i++) 41 head[i]=ans[i]=-1,du[i]=tot[i]=0; 42 for(int i=1;i<n;i++) 43 { 44 cin>>u1>>v1; 45 add(u1,v1),du[u1]++; 46 add(v1,u1),du[v1]++; 47 } 48 cin>>s; 49 for(int i=0;i<n;i++) 50 c[i+1]=s[i]=='W'; 51 if(!dfs(1,0)) 52 { 53 cout<<-1<<'\n'; 54 return ; 55 } 56 for(int i=1;i<=n;i++) 57 ans[i]?cout<<"W":cout<<"B"; 58 cout<<'\n'; 59 } 60 int main() 61 { 62 ios::sync_with_stdio(false); 63 cin.tie(0);cout.tie(0); 64 cin>>T; 65 for(int i=1;i<=T;i++) 66 solve(); 67 return 0; 68 }
四、写题心得:
我突然发现这根本就不是什么心得,而是我的吐槽。
这次 $arc$ 感觉比以前要简单一些(也有可能是我变强了$qwq$),但是我忘了这场比赛,导致迟到了!
所以是 $unrated$ ,写起来一点动力都没有,$C$ 题以为把题理解错了一直没写出来,还耽搁了特别水的 $D$ 题。
不过问题不大。加油吧!拜拜!
浙公网安备 33010602011771号