UVALive 4452 The Ministers' Major Mess(2-sat)

2-sat。又学到了一种使用的方法:当确定选择某中状态A时,从它的对立状态A^1引一条边add(A^1,A),从而使凡是dfs经过对立状态,必然return false;即保证若存在一种可能性,必然是经过该状态A的。

题意:m个人对n个方案投票,每人之多投4票,是否存在一种方案使每个人所投的一半以上的票被采纳。依次输出每个议题最终的结果。

1、注意是一半以上,我一开始理解成一半,结果无法根据必然性建边。<=2票则都被采纳,<=4票则至多有一票不被采纳。

2、输出时要注意,因为每个议题的结果都不一定相同,所以需要一一判断。需要分别进行solve(i),和solve(i+1)。这里一开始我直接是把solve()函数中的dfs(i)和dfs(i+1)分开,wa了,后来考虑发现,solve()一次,是对遍历整个方案寻找可行性;而dfs()只是对一个连通的量做了标记。

注意:分别检查同一个议题的两种状态,确定从状态A经过,add(A^1,A),结束要记得G[i].pop_back();

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int MAXN=555;
  8 
  9 struct Vote{
 10     int v,c;
 11 }vote[MAXN][5];
 12 
 13 bool mark[MAXN<<1];
 14 int res[MAXN];
 15 int s[MAXN<<1],c;
 16 vector<int >G[MAXN<<1];
 17 
 18 void init(int n)
 19 {
 20     for(int i=0;i<(n<<1);i++)
 21         G[i].clear();
 22     memset(mark,0,sizeof(mark));
 23 }
 24 
 25 void add(int x,int dx,int y,int dy)
 26 {
 27     x=(x<<1)+dx;
 28     y=(y<<1)+dy;
 29     G[x].push_back(y);
 30 }
 31 
 32 bool dfs(int x)
 33 {
 34     if(mark[x^1])
 35         return false;
 36     if(mark[x])
 37         return true;
 38     s[c++]=x;
 39     mark[x]=true;
 40     for(int i=0;i<G[x].size();i++)
 41         if(!dfs(G[x][i]))
 42             return false;
 43     return true;
 44 }
 45 
 46 bool solve(int n)
 47 {
 48     for(int i=0;i<(n<<1);i+=2)
 49     {
 50         if(!mark[i]&&!mark[i+1]){
 51             c=0;
 52             if(!dfs(i)){
 53                 while(c>0)
 54                     mark[s[--c]]=false;
 55                 if(!dfs(i+1))
 56                     return false;
 57             }
 58         }
 59     }
 60     return true;
 61 }
 62 
 63 bool test(int n)
 64 {
 65     for(int i=0;i<n;i++)
 66     {
 67         int ans=0;
 68         memset(mark,0,sizeof(mark));
 69         add(i,1,i,0);
 70         while(c>0)
 71             mark[s[--c]]=false;
 72         if(solve(n))
 73             ans+=1;
 74         G[(i<<1)+1].pop_back();
 75         
 76         memset(mark,0,sizeof(mark));
 77         add(i,0,i,1);
 78         while(c>0)
 79             mark[s[--c]]=false;
 80         if(solve(n))
 81             ans+=2;
 82         G[i*2].pop_back();
 83 
 84         if(ans==0)
 85             return false;
 86         else if(ans==1)
 87             res[i]=-1;
 88         else if(ans==2)
 89             res[i]=1;
 90         else if(ans==3)
 91             res[i]=0;
 92     }
 93     return true;
 94 }
 95 
 96 int main()
 97 {
 98     int n,m;
 99     int cnt=0,ans;
100     while(~scanf("%d%d",&n,&m))
101     {
102         if(!n&&!m)
103             return 0;
104 
105         init(n);         //!!
106         for(int i=0;i<m;i++)
107         {
108             scanf("%d",&ans);
109 
110             for(int j=0;j<ans;j++)
111             {
112                 int x;
113                 char ch[2];
114                 scanf("%d %s",&x,ch);
115                 vote[i][j].v=--x;
116                 if(ch[0]=='y')
117                     vote[i][j].c=1;
118                 else
119                     vote[i][j].c=0;
120             }
121             if(ans<=2){
122                 for(int j=0;j<ans;j++)
123                     add(vote[i][j].v,vote[i][j].c^1,vote[i][j].v,vote[i][j].c);
124             }else
125                 for(int j=0;j<ans;j++)
126                     for(int k=0;k<ans;k++)
127                     {
128                         if(j==k)
129                             continue;
130                         add(vote[i][j].v,vote[i][j].c^1,vote[i][k].v,vote[i][k].c);
131                     }
132         }
133 
134         memset(res,0,sizeof(res));
135         printf("Case %d: ",++cnt);
136         if(!test(n))
137             printf("impossible\n");
138         else {
139             for(int i=0;i<n;i++)
140             {
141                 if(res[i]==0)
142                     printf("?");
143                 else if(res[i]==1)
144                     printf("y");
145                 else if(res[i]==-1)
146                     printf("n");
147             }
148             printf("\n");
149         }
150     }
151     return 0;
152 }
153 /*
154 5 3
155 2 1 y 2 n
156 3 1 y 3 n 4 y
157 4 1 n 3 n 4 n 5 y
158 */
View Code

 

posted @ 2013-08-09 00:01  Thousand Sunny  阅读(333)  评论(0编辑  收藏  举报