【题目链接】
http://poj.org/problem?id=3648
【题目大意】
有n-1对夫妇被一对新郎新娘邀请来参加婚礼,他们要坐在一条长桌上,可以选择坐在左边或者右边。每对夫妻都不能坐在同一边,他们只能是面对面坐着。
但是这些人中有JQ,共有m对有JQ(新郎也可能有奸情,可怜的新娘...)。要求这些JQ对不能同时坐在新娘的对面。即,每一对JQ者,他们可以同时坐在和新娘同一边,也可以一个和新娘同一边而另一个在新娘对面即可。
要求找到一种方案并输出,如果没有方案输出bad luck
【思路】
对于每一对夫妇,有两种选择,要么女方和新娘同一边,要么男方和新娘坐在同一边。
然后是根据JQ关系加边。
【代码】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define WHITE -1 #define RED 1 #define BLUE 0 using namespace std; typedef long long int64; const int MAXN = 50; const int VN = MAXN*2; const int EN = VN*VN; int n, m; struct Edge{ int u, v, next; }; struct Graph{ int size, head[VN]; Edge E[EN]; void init(){size=0; memset(head, -1, sizeof(head));}; void addEdge(int u, int v){ E[size].u = u; E[size].v = v; E[size].next = head[u]; head[u] = size++; } }g, g1; class Two_Sat{ public: bool check(const Graph&g, const int n){ scc(g, 2*n); for(int i=0; i<n; ++i) if(belong[i] == belong[i+n]) return false; return true; } void toposort(const Graph& g, Graph& g1, const int n){ g1.init(); memset(indeg, 0, sizeof(indeg)); for(int i=0; i<n; ++i){ opp[belong[i]] = belong[i+n]; opp[belong[i+n]] = belong[i]; } for(int e=0; e<g.size; ++e){ int u = belong[g.E[e].u]; int v = belong[g.E[e].v]; if(u==v) continue; ++indeg[u]; g1.addEdge(v, u); } queue<int>que; memset(color, WHITE, sizeof(color)); for(int i=1; i<=bcnt; ++i) if(!indeg[i]) que.push(i); while(!que.empty()){ int u = que.front(); que.pop(); if(color[u] != WHITE) continue; color[u] = RED; color[opp[u]] = BLUE; for(int e=g1.head[u]; e!=-1; e=g1.E[e].next){ int v = g1.E[e].v; if(--indeg[v] == 0){ que.push(v); } } } // 输出方案 printf("1%c",color[belong[1]]==RED?'w':'h'); for(int i=2; i<n; ++i){ printf(" %d%c", i, color[belong[i]]==RED?'w':'h'); } puts(""); } private: void tarjan(const Graph&g, const int u){ int v; DFN[u] = low[u] = ++idx; sta[top++] = u; instack[u] = true; for(int e=g.head[u]; e!=-1; e=g.E[e].next){ v = g.E[e].v; if(DFN[v] == -1){ tarjan(g, v); low[u] = min(low[u], low[v]); }else if(instack[v]){ low[u] = min(low[u], DFN[v]); } } if(DFN[u] == low[u]){ ++bcnt; do{ v = sta[--top]; instack[v] = false; belong[v] = bcnt; }while(u != v); } } void scc(const Graph& g, const int n){ idx = top = bcnt = 0; memset(DFN, -1, sizeof(DFN)); memset(instack, 0, sizeof(instack)); for(int i=0; i<n; ++i) if(DFN[i] == -1) tarjan(g, i); } private: int idx, top, bcnt; int DFN[VN], low[VN], belong[VN], sta[VN]; bool instack[VN]; int color[VN], opp[VN], indeg[VN]; }sat; int main(){ char ch1, ch2; int a, b; while(~scanf("%d%d", &n, &m) && n+m){ g.init(); g.addEdge(n, 0); //注意要添加这个!因为新郎也可能有奸情 for(int i=0; i<m; ++i){ scanf("%d%c%d%c",&a,&ch1,&b,&ch2); if(ch1=='h' && ch2=='h'){ g.addEdge(a, b+n); g.addEdge(b, a+n); }else if(ch1=='h' && ch2=='w'){ g.addEdge(a, b); g.addEdge(b+n, a+n); }else if(ch1=='w' && ch2=='h'){ g.addEdge(a+n, b+n); g.addEdge(b, a); }else if(ch1=='w' && ch2=='w'){ g.addEdge(a+n, b); g.addEdge(b+n, a); } } if(!sat.check(g, n)) puts("bad luck"); else{ sat.toposort(g, g1, n); } } return 0; }