BZOJ2199: [Usaco2011 Jan]奶牛议会

时间:2023-12-21 22:41:14

趁此机会学了一下2-SAT。

以前的2-SAT都是用并查集写的,只能应用于极小的一部分情况,这次学了一正式的2-SAT,是用一张有向图来表示其依赖关系。

2-SAT的介绍参见刘汝佳《训练指南》。

 /**************************************************************
Problem: 2199
User: zhuohan123
Language: C++
Result: Accepted
Time:140 ms
Memory:1388 kb
****************************************************************/ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m;
struct point{int y,n;}p[];int pnum;
int head[];
struct edge{int next,to;}g[];int gnum;
void addedge(int from,int to)
{
g[++gnum].to=to;g[gnum].next=head[from];head[from]=gnum;
}
int q[],l,r;
bool cango[];
bool check(int po)
{
memset(cango,,sizeof cango);
cango[po]=true;l=;r=;q[++r]=po;
while(l<=r)
for(int i=head[q[l++]];i;i=g[i].next)
if(!cango[g[i].to])cango[q[++r]=g[i].to]=true;
for(int i=;i<=n;i++)
if(cango[p[i].y]&&cango[p[i].n])return false;
return true;
}
char ans[];
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)p[i].n=++pnum,p[i].y=++pnum;
while(m--)
{
int b,c;char vb[],vc[];
scanf("%d%s%d%s",&b,vb,&c,vc);
if(vb[]=='Y'&&vc[]=='Y')addedge(p[b].n,p[c].y),addedge(p[c].n,p[b].y);
if(vb[]=='Y'&&vc[]=='N')addedge(p[b].n,p[c].n),addedge(p[c].y,p[b].y);
if(vb[]=='N'&&vc[]=='Y')addedge(p[b].y,p[c].y),addedge(p[c].n,p[b].n);
if(vb[]=='N'&&vc[]=='N')addedge(p[b].y,p[c].n),addedge(p[c].y,p[b].n);
}
for(int i=;i<=n;i++)
{
bool by=check(p[i].y),bn=check(p[i].n);
if(by&&bn)ans[i]='?';
else if(by)ans[i]='Y';
else if(bn)ans[i]='N';
else {puts("IMPOSSIBLE");return ;}
}
puts(ans+);
return ;
}

P.S.这个代码写的相当非主流啊!