这题说的是 在一个 森林中 两个人在这棵树上涂颜色,黑色或者白色,第一次只能在1 号节点上涂色 第二次 只能在2上涂,以此类推, 在每个节点上只能涂黑色或者白色,并且相邻的点不能有相同的颜色,最后求不能填的人就输了。
每个点周围的比他小的点 都会有一个祖先(或者是他们自己),我们知道他周围的点的祖先中最小的那个点 一定是影响他的最小的点 那么他取什么值这就不那么重要了。无论他取黑还是白,后面的就只是相对而言,那么如果他受到第二小或者以上的点的影响,那么他就一定不能了, 还有就是当他和他周围点离他们共同祖先的距离一样的时候也是不行的。
哪个先出现错误哪个就失败了。
#include <iostream> #include <algorithm> #include<string.h> #include<vector> #include <cstdio> using namespace std; const int maxn=100005; struct Edg{ int to,nxt; Edg(int a=0,int b=0){ to=a; nxt=b; } }P[maxn*5]; int len[maxn],fa[maxn],first[maxn],pos; void add(int a, int b){ P[pos].to=b; P[pos].nxt=first[a]; first[a]=pos++; } int find(int x){ if(x!=fa[x]){ int f=find(fa[x]); len[ x ] = len[ fa[x] ]^len[x]; fa[ x ] = f; } return fa[x]; } bool uunion(int x, int y){ int fx=find(x); int fy=find(y); if(fx==fy){ return len[x]!=len[y]; } if(fx<fy){ fa[fy]=fx; len[fy ] = len[x]^len[y]^1; }else{ fa[fx]=fy; len[fx] = len[x]^len[y]^1; } return true; } int qq[maxn*2]; int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); int N,M,cas; scanf("%d",&cas); for(int cc=1; cc<=cas; cc++){ pos=0; scanf("%d%d",&N,&M); for(int i=0; i<=N; i++){ first[i]=0; fa[i]=i; len[i]=0; } for(int i=0; i<M; i++){ int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } int ans=-1; for(int i=1; i<=N&&ans==-1; i++){ int pp=0; for(int j=first[i]; j ; j=P[j].nxt){ int to=P[j].to; if(to>i)continue; qq[pp++]=find(to); } sort(qq,qq+pp); pp = unique(qq,qq+pp)-qq; for(int j=1; j<pp; j++) if( qq[j]%2 != i%2 )ans=i; for(int j=first[i]; j; j=P[j].nxt){ int to=P[j].to; if(to>i) continue; if(!uunion(i,to))ans=i; } } printf("Case %d: ",cc); if(ans==-1)printf("Draw "); else{ if( (ans&1) ==0)printf("Maze "); else printf("Fat Brother "); } } return 0; }