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 }
View Code

 

posted @ 2017-08-26 13:15  Blue233333  阅读(292)  评论(0编辑  收藏  举报