ARC143E Reversi
题面传送门
首先有经典结论:在一的个数为偶数时无解。
显然如果一的个数为偶数的时候最后会有两个相邻点都是\(1\)的情况,这种情况下无论消哪一个另外一个都没有办法被消掉。而奇数只要每次删最深的一个点就可以删完。
然后来考虑字典序的问题。先来考虑叶子节点,如果某一个叶子节点是白的,那么这个叶子节点一定要在它的父亲前操作掉,否则要在父亲后操作掉。然后将现在的叶子节点这一层剥掉之后继续。因此可以建立一张DAG,然后跑拓扑即可得到字典序最小的答案。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (1000000+5)
#define M (100000+5)
#define K (2500+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;vector<int> S[N],G[N];
int n,x,y,In[N];char c[N];priority_queue<int,vector<int>,greater<int> > Q;
I void Make(int x,int La){for(int i:S[x]) i^La&&(Make(i,x),0);La&&(c[x]?(c[La]^=1,G[x].PB(La),In[La]++):(G[La].PB(x),In[x]++));}
int main(){
freopen("1.in","r",stdin);
int i,j,YZXAKIOI=0;scanf("%d",&n);for(i=1;i<n;i++) scanf("%d%d",&x,&y),S[x].PB(y),S[y].PB(x);scanf("%s",c+1);for(i=1;i<=n;i++) YZXAKIOI^=(c[i]=(c[i]!='B'));
if(!YZXAKIOI) {puts("-1");return 0;}Make(1,0);for(i=1;i<=n;i++) !In[i]&&(Q.push(i),0);while(!Q.empty()){x=Q.top();Q.pop();printf("%d ",x);for(int i:G[x]) In[i]--,!In[i]&&(Q.push(i),0);}
}

浙公网安备 33010602011771号