題意:一對新婚的夫婦邀請(n-1)對夫婦來參加自己的宴會,這對新人以及這些受邀請的夫婦都坐在長桌子的兩邊,新娘和新郎分別坐在桌子的兩側,新娘不希望看到她邀請來的那些夫婦之中有妻子和丈夫坐在同一邊的情況(即妻子和丈夫要分作桌子的兩邊),在這n對夫婦中有一些男女存在著曖昧的關係,所以新娘也不希望看到有曖昧關係的人坐在她對面的那一側.求解是否存在一種滿足新娘要求的座位分配方案,如果存在的話,那麼就輸出這方案,否則輸出"bad
luck".
新娘編號為0,新郎編號為1,即將妻子編號為2*i,丈夫編號為2*i+1,對於曖昧關係x y,加邊x->y', y->x',因為需要輸出和新娘坐在同一邊的方案,所以這裡應該以新娘為標準得到需要的解,這裡由於新郎和新娘不能坐在同一邊,所以加邊0->1.
#define N 1004vector<int> v[N];vector<int> g[N];stack<int> s;bool vis[N];bool inStack[N];int low[N],dfn[N];int belong[N];//屬於哪個強連通分量int n,m,step,t;int conflict[N];int col[N];int in[N];void init(){ int i; for(i=0;i<=2*n;i++){ v[i].clear(); vis[i] = 0; inStack[i] = 0; in[i] = 0; g[i].clear(); col[i] = 0; } while(!s.empty())s.pop();}void add(int a,int b){ v[a].push_back(b);}//tarjan縮點void tarjan(int u){ vis[u]=true; step++; s.push(u); inStack[u]=true; low[u]=step,dfn[u]=step; int i,j; for(i=0;i<v[u].size();i++) { int x=v[u][i]; if(!vis[x]) { tarjan(x); low[u]=min(low[u],low[x]); } else if(inStack[x]) low[u]=min(low[u],dfn[x]); } if(low[u]==dfn[u]) { t++; while(1) { int x=s.top(); s.pop(); belong[x]=t; inStack[x]=false; if(x==u)break; } }}//反向建圖,因為最後是自底向上拓撲,因此反向後就變成了一般的自上向下拓撲,方便實現void rebuild(){ int i,j; for(i=0;i<2*n;i++){ for(j=0;j<v[i].size();j++){ int a = belong[i],b = belong[v[i][j]]; if(a!=b){ in[a]++; g[b].push_back(a); } } }}void topsort(){ int i,j; queue<int> qq; for(i=1;i<=t;i++){//現在對縮點後的圖進行拓撲 if(!in[i]){ qq.push(i); } } while(!qq.empty()){ int u = qq.front();qq.pop(); if(!col[u]){ col[u] = 1;//紅色 col[conflict[u]] = 2;//藍色(因為縮點後變成有向非循環圖,對應的衝突點只有確定的一個) } for(i=0;i<g[u].size();i++){ int vv = g[u][i]; in[vv]--; if(!in[vv])qq.push(vv); } }}void solve(){ t = 0,step = 0; int i,j; for(i=0;i<2*n;i++){ if(!vis[i])tarjan(i); } for(i=0;i<2*n;i+=2){ if(belong[i] == belong[i+1]){//矛盾點在同一個強連通分量 puts("bad luck"); return ; } int a = belong[i],b = belong[i+1]; conflict[a] = b; conflict[b] = a; } rebuild(); topsort(); for(i=2;i<2*n;i+=2){ if(i!=2)printf(" "); if(col[belong[i]] == col[belong[0]]){//如果女的與新娘同色,就取她 printf("%dw",i/2); } else printf("%dh",i/2);//否則,取她的老公 } puts("");}int main(){ while(scanf("%d%d",&n,&m) && (n+m)){ int i,j,ii,jj; init(); char c1,c2; int d1,d2; while(m--){ scanf("%d%c %d%c",&d1,&c1,&d2,&c2); if(c1 == 'h'){ i = 2*d1+1;//man ii = i-1;//woman } else { i = 2*d1;//woman ii = i+1;//man } if(c2 == 'h'){ j = 2*d2+1;//man jj = j-1;//woman } else { j = 2*d2;//woman jj = j+1;//man } add(i,jj);//i->j' add(j,ii);//j->i' //cout<<i<<" "<<ii<<endl; //cout<<j<<" "<<jj<<endl<<endl; } add(0,1); solve(); } return 0;}