题意:有个新娘和新郎,然后请了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;
}