题意:有个新娘和新郎,然后请了n-1对夫妇,其中有m对有不正当关系……而新娘不想看到有不正当关系的在一起,新娘可以看到在她对面的人,而在她同一边的看不到,所以即使有不正当关系的在新娘同一边也是可以的。问:有没有可能的方案符合题意?
这题看了一天了……还是没弄明白其建图是什么回事……唉……看了魏神的博客,然后还是研究了好久,不知道为什么那样建图,晕……等过段时间再回来看再理解吧!
就把这个作为2SAT求解方案的模板咯,嘿嘿……
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <list> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) #define sca(a) scanf("%d",&a) #define sc(a,b) scanf("%d%d",&a,&b) #define pri(a) printf("%d\n",a) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define MM 1000005 #define MN 100050 #define INF 1000000009 #define eps 1e-7 using namespace std; typedef long long ll; typedef unsigned long long ULL; int DFN[MN],LOW[MN],vis[MN],belong[MN]; int n,m,index,Count,conflict[MN],color[MN],id[MN]; stack<int>Stack,q; vector<int>e[MN],ee[MN]; //e为原图,ee为新图 void init() { index=Count=0; mem(vis,0); mem(DFN,0); mem(LOW,0); mem(belong,0); mem(conflict,0); mem(color,0); mem(id,0); for(int i=0;i<=2*n;i++) e[i].clear(),ee[i].clear(); while(!Stack.empty()) Stack.pop(); } void tarjan(int u) { DFN[u]=LOW[u]=++index; vis[u]=1; Stack.push(u); int v,i,l=e[u].size(); for(i=0;i<l;i++) { v=e[u][i]; if(!DFN[v]) { tarjan(v); LOW[u]=min(LOW[u],LOW[v]); } else if(vis[v]&&DFN[v]<LOW[u]) LOW[u]=DFN[v]; } if(DFN[u]==LOW[u]) { Count++; do { v=Stack.top(); Stack.pop(); vis[v]=0; belong[v]=Count; }while(v!=u); } } void topsort() //对新图拓扑排序并颜色标记 { int i,u,len; for(i=1;i<=Count;i++) if(!id[i]) q.push(i); while(!q.empty()) { u=q.top(); q.pop(); len=ee[u].size(); if(!color[u]) color[u]=1,color[conflict[u]]=2; for(i=0;i<len;i++) if(--id[ee[u][i]]==0) q.push(ee[u][i]); } } void buildMap() //建立新图 { int u,v,i,len; for(u=0;u<2*n;u++) { len=e[u].size(); for(i=0;i<len;i++) { v=e[u][i]; if(belong[u]!=belong[v]) ee[belong[v]].push_back(belong[u]),id[belong[u]]++; } } } void twoSAT() { int i; for(i=0;i<2*n;i++) if(!DFN[i]) tarjan(i); for(i=0;i<n;i++) if(belong[2*i]==belong[2*i+1]) { puts("bad luck"); return ; } else conflict[belong[2*i]]=belong[2*i+1], conflict[belong[2*i+1]]=belong[2*i]; //不同的强连通就是冲突 buildMap(); topsort(); for(i=2;i<2*n;i+=2) if(color[belong[i]]==color[belong[0]]) printf("%dw ",i/2); else printf("%dh ",i/2); puts(""); } int main() { int a0,b0,b1,a1,x,y,i,j; char c1,c2; while(sc(n,m)&&(n||m)) { init(); while(m--) { scanf("%d%c %d%c",&x,&c1,&y,&c2); if(c1 == 'h') a0 = 2 * x, a1 = 2 * x + 1; else a0 = 2 * x + 1, a1 = 2 * x; //为什么要这样建图还是弄不明白…… if(c2 == 'h') b0 = 2 * y, b1 = 2 * y + 1; else b0 = 2 * y + 1, b1 = 2 * y; e[a1].push_back(b0); e[b1].push_back(a0); } e[0].push_back(1); twoSAT(); } return 0; }