题目链接:https://vjudge.net/contest/166461#problem/C
题意:
n对夫妻,有m对人吵过架,不能排在同一边,求新娘的一边的人;
分析:
每对夫妻,看成两个点,女的 2i,男的2i+1,吵架了的关系,就是必然关系,必须满足,不能在同一边;再用2-SAT
#include <bits/stdc++.h> using namespace std; const int maxn = 5000+5; struct TwoSAT { int n; vector<int> G[maxn*2]; bool mark[maxn*2]; int S[maxn*2],cnt; bool dfs(int u) { if(mark[u^1]) return false; if(mark[u]) return true; mark[u]=1; S[cnt++]=u; for(int i=0; i<G[u].size(); ++i) if(!dfs(G[u][i])) return false; return true; } void init(int n) { this ->n = n; for(int i=0; i<n*2; i++) G[i].clear(); memset(mark,0,sizeof(mark)); } // x = xval or y = yval void add_clause(int x,int xval,int y,int yval) { x = x*2 + xval; y = y*2 + yval; G[x^1].push_back(y); G[y^1].push_back(x); } bool solve() { for(int i=0; i<n*2; i+=2) { if(!mark[i]&&!mark[i+1]) { cnt = 0; if(!dfs(i)) { if(i==0) return false; while(cnt>0) mark[S[--cnt]] = false; if(!dfs(i+1)) return false; } } } return true; } } sol; int main() { int n,m; while(scanf("%d%d",&n,&m),n) { sol.init(n); char p[2][3]; int a,b; while(m--) { scanf("%d%s%d%s",&a,p[0],&b,p[1]); int u=0,v=0; if(p[0][0]=='h') u=1; if(p[1][0]=='h') v=1; sol.add_clause(a,u,b,v); } if(!sol.solve()) printf("bad luck "); else { for(int i=1; i<n; ++i) printf("%d%c%c",i,sol.mark[i<<1]?'w':'h',(i==n-1)?' ':' '); } } return 0; }