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.这个代码写的相当非主流啊!

posted @ 2013-08-27 16:32  zhuohan123  阅读(322)  评论(0编辑  收藏  举报