BZOJ2199: [Usaco2011 Jan]奶牛议会

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

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

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

 1 /**************************************************************

 2     Problem: 2199

 3     User: zhuohan123

 4     Language: C++

 5     Result: Accepted

 6     Time:140 ms

 7     Memory:1388 kb

 8 ****************************************************************/

 9  

10 #include <iostream>

11 #include <cstdio>

12 #include <cstring>

13 #include <algorithm>

14 using namespace std;

15 int n,m;

16 struct point{int y,n;}p[1100];int pnum;

17 int head[2100];

18 struct edge{int next,to;}g[11000];int gnum;

19 void addedge(int from,int to)

20 {

21     g[++gnum].to=to;g[gnum].next=head[from];head[from]=gnum;

22 }

23 int q[2100],l,r;

24 bool cango[2100];

25 bool check(int po)

26 {

27     memset(cango,0,sizeof cango);

28     cango[po]=true;l=1;r=0;q[++r]=po;

29     while(l<=r)

30         for(int i=head[q[l++]];i;i=g[i].next)

31             if(!cango[g[i].to])cango[q[++r]=g[i].to]=true;

32     for(int i=1;i<=n;i++)

33         if(cango[p[i].y]&&cango[p[i].n])return false;

34     return true;

35 }

36 char ans[1100];

37 int main(int argc, char *argv[])

38 {

39     #ifndef ONLINE_JUDGE

40         freopen("1.in","r",stdin);

41         freopen("1.out","w",stdout);

42     #endif

43     scanf("%d%d",&n,&m);

44     for(int i=1;i<=n;i++)p[i].n=++pnum,p[i].y=++pnum;

45     while(m--)

46     {

47         int b,c;char vb[4],vc[4];

48         scanf("%d%s%d%s",&b,vb,&c,vc);

49         if(vb[0]=='Y'&&vc[0]=='Y')addedge(p[b].n,p[c].y),addedge(p[c].n,p[b].y);

50         if(vb[0]=='Y'&&vc[0]=='N')addedge(p[b].n,p[c].n),addedge(p[c].y,p[b].y);

51         if(vb[0]=='N'&&vc[0]=='Y')addedge(p[b].y,p[c].y),addedge(p[c].n,p[b].n);

52         if(vb[0]=='N'&&vc[0]=='N')addedge(p[b].y,p[c].n),addedge(p[c].y,p[b].n);

53     }

54     for(int i=1;i<=n;i++)

55     {

56         bool by=check(p[i].y),bn=check(p[i].n);

57         if(by&&bn)ans[i]='?';

58         else if(by)ans[i]='Y';

59         else if(bn)ans[i]='N';

60         else {puts("IMPOSSIBLE");return 0;}

61     }

62     puts(ans+1);

63     return 0;

64 }

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

你可能感兴趣的:(USACO)