您的位置:首页 > 其它

POJ 3648 Wedding 2-sat输出一组解

2015-11-02 15:49 501 查看
题目:n对夫妻,参加婚礼,一对夫妻不能坐在桌子的同一侧,m对有性爱关系的*男*女不能坐在桌子的同一侧,新娘新郎必须坐上桌子,输出任意一种新娘对面坐的人的情况。

这个肯定就是2-sat问题,建图时注意建新郎和新娘的边,还有缩点构造新图的时候返向建边,因为当有一条边a->b的时候,表示选a必须选b那么这样我们在选择人的时候,就会有一连串的问题,但是我们直接选b但是他可以不一定选择a,这个新图是个对称的图,因为2-sat问题建图后又很强的对称性,一个最基本的关系是题目给你的m对关系,隐含的就是夫妻关系,他们是排斥的关系,所以要标记这个关系,topsort的时候夫妻一方被选另一方自动到桌子的对面。



#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
const int nodes=1000;
const int edges=100000;
struct node
{
int v,next;
}e[nodes];
int n,m;
int conflict[nodes],dis[nodes],in[nodes];
int head[nodes],cnt;
vector<int>ve[nodes];
stack<int>s;
int low[nodes],dfn[nodes],paint[nodes],instack[nodes],index,col;
void Init()
{
while(!s.empty()) s.pop();
for(int i=0;i<=nodes;i++) ve[i].clear();
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(paint,0,sizeof(paint));
memset(instack,0,sizeof(instack));
memset(head,-1,sizeof(head));
index=col=1;
cnt=0;
}
void add(int a,int b)
{
e[cnt].v=b;
e[cnt].next=head[a];
head[a]=cnt++;
}
int MIN(int a,int b)
{
if(a<b) return a;
return b;
}
void tarjan(int u)
{
dfn[u]=low[u]=index++;
instack[u]=1;
s.push(u);
for(int i=head[u];i+1;i=e[i].next)
{
int v=e[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=MIN(low[u],low[v]);
}
else if(instack[v])
{
low[u]=MIN(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
int k=s.top();
while(k!=u)
{
s.pop();
paint[k]=col;
instack[k]=0;
k=s.top();
}
s.pop();
paint[u]=col;
instack[u]=0;
col++;
}
}
void Input()
{
for(int i=1;i<=m;i++)
{
int a,b;
int aa,bb;
char ch1,ch2;
scanf("%d%c %d%c",&a,&ch1,&b,&ch2);
if(ch1=='h')
{
a=a+n;
aa=a-n;
}
else
{
aa=a+n;
}
if(ch2=='h')
{
b=b+n;
bb=b-n;
}
else
{
bb=b+n;
}
add(a,bb);
add(b,aa);
}
add(0,n);
}
void topsort()
{
queue<int>q;
while(!q.empty()) q.pop();
for(int i=0;i<2*n;i++)
{
if(!in[i])
q.push(i);
}
while(!q.empty())
{
int u=q.front();
q.pop();
if(!dis[u])
{
dis[u]=1;
dis[conflict[u]]=2;
}
for(int i=0;i<ve[u].size();i++)
{
int v=ve[u][i];
if(--in[v]==0)
{
q.push(v);
}
}
}
}
void Output()
{
memset(conflict,0,sizeof(conflict));
memset(dis,0,sizeof(dis));
memset(in,0,sizeof(in));
for(int i=0;i<n;i++)
{
conflict[paint[i]]=paint[i+n];
conflict[paint[i+n]]=paint[i];
}
for(int i=0;i<2*n;i++)
{
for(int j=head[i];j+1;j=e[j].next)
{
int v=e[j].v;
if(paint[i]!=paint[v])
{
ve[paint[v]].push_back(paint[i]);
in[paint[i]];
}
}
}
topsort();
for(int i=1;i<n;i++)
{
if(i!=1) printf(" ");
if(dis[paint[i]]==dis[paint[0]])
{
printf("%dw",i);
}
else printf("%dh",i);
}
}
void treatment()
{
int mark=1;
for(int i=0;i<2*n;i++)
{
if(!dfn[i]) tarjan(i);
}
col--;
for(int i=0;i<n;i++)
{
if(paint[i]==paint[i+n])
{
mark=0;
break;
}
}
if(!mark) printf("bad luck\n");
else Output();
}
int main()
{
while(~scanf("%d%d",&n,&m),n+m)
{
Init();
Input();
treatment();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: