poj 3648

来源:互联网 发布:淘宝的盈利模式 编辑:程序博客网 时间:2024/06/06 20:51

一对夫妻举行婚礼,有最多30对夫妻参加,其中新娘新郎必须坐在桌子两侧。新娘看不到她所在一侧的人, 只能看到对面的人。新娘看到一对夫妻坐在一边是不吉利的。除此之外,有些人又通奸关系。看到有通奸关系的人左一边也是不吉利的。求出新娘一侧坐的人。

每个人只有两个选择,根据通奸关系建图,然后2—sat求解。

0表示新郎,1表示新娘,加一条0—>1的边,这样就可以保证选的一组解一定是新娘一边的人。

AC代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=100;
stack<int> S;
int first[maxn],rfirst[maxn],tar[maxn],sta[maxn],dfn[maxn],low[maxn],in[maxn],ret[maxn];
int size,rsize,cnt,index,n,m;
struct Edge
{
 int v,next;
}edge[maxn*maxn],redge[maxn*maxn];
void insert(int u,int v)
{
 edge[size].v=v;
 edge[size].next=first[u];
 first[u]=size++;
}
void rinsert(int u,int v)
{
 redge[rsize].v=v;
 redge[rsize].next=rfirst[u];
 rfirst[u]=rsize++;
}
void tarjan(int u)
{
 sta[u]=1; S.push(u);
 dfn[u]=low[u]=++index;
 for(int e=first[u];e!=-1;e=edge[e].next)
 {
  int v=edge[e].v;
  if(!dfn[v])
  {
   tarjan(v);
   low[u]=min(low[u],low[v]);
  }
  else if(sta[v]) low[u]=min(low[u],dfn[v]);
 }
 if(dfn[u]==low[u])
 {
  int v=-1; cnt++;
  while(v!=u)
  {
   v=S.top(); S.pop();
   tar[v]=cnt; sta[v]=0;
  }

 }
}
void slove()
{
 cnt=index=0;
 memset(dfn,0,sizeof(dfn));
 memset(sta,0,sizeof(sta));
 for(int i=0;i<2*n;i++)
  if(!dfn[i]) tarjan(i);
}
int check()
{
 for(int i=0;i<n;i++)
  if(tar[2*i]==tar[2*i+1])
   return 0;
 return 1;
}
void topsort()
{
 for(int i=0;i<cnt;)
  for(int j=1;j<=cnt;j++)
   if(!in[j])
   {
    in[j]--; ret[i++]=j; 
    for(int e=rfirst[j];e!=-1;e=redge[e].next)
     in[redge[e].v]--;
   }
 int flag[maxn];
 memset(flag,0,sizeof(flag));
 for(int i=0;i<cnt;i++)
 {
  for(int j=0;j<2*n;j++)
   if(tar[j]==ret[i] && !flag[j^1])
    flag[j]=1;
 }
 for(int j=2;j<2*n;j++)
  if(!flag[j])
  {
   if(j%2) printf("%dh ",j/2);
   else printf("%dw ",j/2);
  }
 printf("\n");
}

int main()
{
// freopen("test.txt","r",stdin);
 while(scanf("%d%d",&n,&m) && n && m)
 {
  memset(first,-1,sizeof(first)); size=0;
  memset(rfirst,-1,sizeof(rfirst)); rsize=0;
  insert(0,1);
  for(int i=0;i<m;i++)
  {
   int u,v; char cu,cv;
   scanf("%d%c%d%c",&u,&cu,&v,&cv);
  
   if(cu=='w' && cv=='w')
   { insert(2*u,2*v+1); insert(2*v,2*u+1); }
   if(cu=='w' && cv=='h')
   { insert(2*u,2*v); insert(2*v+1,2*u+1); }
   if(cu=='h' && cv=='w')
   { insert(2*u+1,2*v+1); insert(2*v,2*u); }
   if(cu=='h' && cv=='h')
   { insert(2*u+1,2*v); insert(2*v+1,2*u); }
  }
  slove();
  if(!check()) printf("bad luck\n");
  else
  {
   memset(in,0,sizeof(in));
   for(int u=0;u<2*n;u++)
    for(int e=first[u];e!=-1;e=edge[e].next)
    {
     int v=edge[e].v;
     if(tar[u]!=tar[v])
     {
      rinsert(tar[v],tar[u]);
      in[tar[u]]++;
     }
    }
   topsort();
  }
 }
 return 0;
}

原创粉丝点击