BZOJ2199: [Usaco2011 Jan]奶牛议会
m<=4000条关系描述n<=1000个事件,每条关系描述了一个或语句表示“x事件发生或不发生”或“y事件发生或不发生”,求每个事件是必发生、必不发生还是都行,无解输出IMPOSSIBLE。
是一个2-SAT问题。建图后把每个事件发生不发生都dfs一遍即可。听说缩点后会更快,就写了个tarjan。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<math.h> 6 //#include<iostream> 7 using namespace std; 8 9 int n,m; 10 #define maxn 2017 11 #define maxm 10011 12 struct Graph 13 { 14 struct Edge{int to,next;}edge[maxm]; 15 int first[maxn],le;int n; 16 Graph() {memset(first,0,sizeof(first));le=2;} 17 void in(int x,int y) 18 { 19 edge[le].to=y; 20 edge[le].next=first[x]; 21 first[x]=le++; 22 } 23 void addclause(int x,bool xval,int y,bool yval) 24 { 25 x=(x<<1)+xval; 26 y=(y<<1)+yval; 27 in(x^1,y); 28 in(y^1,x); 29 } 30 int Time,low[maxn],dfn[maxn],sta[maxn],top,bel[maxn],tot;bool insta[maxn]; 31 void tarjan(int x) 32 { 33 low[x]=dfn[x]=++Time; 34 sta[++top]=x;insta[x]=1; 35 for (int i=first[x],to=edge[i].to;i;i=edge[i].next,to=edge[i].to) 36 { 37 if (!dfn[to]) tarjan(to),low[x]=min(low[x],low[to]); 38 else if (insta[to]) low[x]=min(low[x],dfn[to]); 39 } 40 if (dfn[x]==low[x]) 41 { 42 tot++; 43 while (sta[top]!=x) bel[sta[top]]=tot,insta[sta[top--]]=0; 44 bel[x]=tot,insta[sta[top--]]=0; 45 } 46 } 47 void tarjan() 48 { 49 memset(dfn,0,sizeof(dfn)); 50 Time=tot=top=0; 51 memset(insta,0,sizeof(insta)); 52 for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i); 53 } 54 }g,tg; 55 bool ok() 56 { 57 for (int i=1;i<=n;i++) 58 if (g.bel[i<<1]==g.bel[(i<<1)^1]) return 0; 59 return 1; 60 } 61 void build() 62 { 63 tg.n=g.tot; 64 for (int i=1;i<=g.n;i++) 65 for (int j=g.first[i],to=g.edge[j].to;j;j=g.edge[j].next,to=g.edge[j].to) 66 if (g.bel[i]!=g.bel[to]) tg.in(g.bel[i],g.bel[to]); 67 } 68 int vis[maxn],Time=0; 69 void dfs(int x) 70 { 71 vis[x]=Time; 72 for (int i=tg.first[x];i;i=tg.edge[i].next) 73 if (vis[tg.edge[i].to]!=Time) dfs(tg.edge[i].to); 74 } 75 bool check(int x) 76 { 77 Time++;dfs(x); 78 for (int i=1;i<=n;i++) 79 if (vis[g.bel[i<<1]]==Time && vis[g.bel[i<<1]]==vis[g.bel[(i<<1)^1]]) return 0; 80 return 1; 81 } 82 char ans[maxn];int x,y;char c[5],d[5]; 83 int main() 84 { 85 scanf("%d%d",&n,&m); 86 g.n=(n<<1)^1; 87 for (int i=1;i<=m;i++) 88 { 89 scanf("%d%s%d%s",&x,c,&y,d); 90 g.addclause(x,c[0]=='Y',y,d[0]=='Y'); 91 } 92 g.tarjan(); 93 if (!ok()) {puts("IMPOSSIBLE");return 0;} 94 build(); 95 for (int i=1;i<=n;i++) 96 { 97 bool x=check(g.bel[i<<1]),y=check(g.bel[(i<<1)^1]); 98 if (x) 99 { 100 if (y) ans[i]='?'; 101 else ans[i]='N'; 102 } 103 else 104 { 105 if (y) ans[i]='Y'; 106 else {puts("IMPOSSIBLE");return 0;} 107 } 108 } 109 ans[n+1]='\0';puts(ans+1); 110 return 0; 111 }