题目描述
题解
2-SAT,和满汉全席差不多
如果一个奶牛的投票是id x jd y的话,那么就连边id x^1->jd y(^表示同一类的不同项)
连出这个图之后,判断每一个点能不能选。也就是说,判断这个点所有能到达的点是否存在冲突(同一类的Y和N都选了),dfs就可以
如果某一类的Y和N都不能选,那么IMPOSSIBLE
否则的话,如果某一个点不能选,那么它同类不同项的那个点必须选;否则的话这两个点选不选都行
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 2005
char s1,s2;
int n,m,id,jd,x,y,cnt;
int tot,point[N],nxt[N*4],v[N*4];
int pt[N][2],chose[N],can[N];
bool vis[N];
void add(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
bool pd(int x,int fa)
{
if (chose[x^1]) return 0;
vis[x]=1;
chose[x]=1;
for (int i=point[x];i;i=nxt[i])
if (!vis[v[i]])
{
int now=pd(v[i],x);
if (!now) return 0;
}
return 1;
}
int main()
{
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;++i) pt[i][0]=cnt++,pt[i][1]=cnt++;
for (int i=1;i<=m;++i)
{
scanf("%d %c %d %c\n",&id,&s1,&jd,&s2);
if (s1=='Y') x=0; else x=1;
if (s2=='Y') y=0; else y=1;
add(pt[id][x^1],pt[jd][y]);
add(pt[jd][y^1],pt[id][x]);
}
for (int i=0;i<2*n;++i)
{
memset(chose,0,sizeof(chose));
memset(vis,0,sizeof(vis));
can[i]=pd(i,0);
}
for (int i=1;i<=n;++i)
if (!can[pt[i][0]]&&!can[pt[i][1]])
{
puts("IMPOSSIBLE");
return 0;
}
memset(chose,0,sizeof(chose));
for (int i=0;i<2*n;++i)
if (!can[i]) chose[i]=-1,chose[i^1]=1;
for (int i=1;i<=n;++i)
if (chose[pt[i][0]]==1) putchar('Y');
else if (chose[pt[i][1]]==1) putchar('N');
else putchar('?');
puts("");
}