• uvalive 4452 The Ministers’ Major Mess


    题意:

    有一些部长需要对某些账单进行投票。

    一个部长最多对4个账单进行投票,且每票对一个账单通过,要么否决。

    问是否存在一个方案使得所有部长有超过半数的投票被通过,如果有,那么说明哪些账单的决定是明确的,哪些是不明确的;否则说明不可能。

    思路:

    2-SAT。

    一开始觉得这是一个k-SAT问题,但是因为有着所有部长的投票有超过半数被通过这个条件存在,所以可以简化。

    对于一票或者两票的部长,那么所有条件都要被满足,意味着某些账单的决定是确定。

    如何表示一个条件是确定的呢,这是从这个题中学习到的一点,不是简单的标记这个条件的真假,而是从自己向自己的对立面连边,如果在搜索的过程中,发现自己和自己的对立面均被标记,那么就产生矛盾从而不满足条件了。

    然后是对于3票或者4票的部长,要超过一半,如果一旦一个账单取相反的决定,那么其它账单都要取与输入相同的决定才能保证查过一半,再根据这个条件连边。

    之后再解决如何确定一个账单的决定是否明确,对于一个账单,如果标记为通过能找到方案,否决也能找到方案,那么这个账单的决定就是不明确的,否则就可以判断其是明确的。在每一次标记了一个条件进行搜索之后,都必须将这个过程中标记过的点全部初始化,才能保证下一次搜索的正确。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <string>
      4 #include <iostream>
      5 #include <vector>
      6 #include <algorithm>
      7 using namespace std;
      8 
      9 const int maxn = 505;
     10 
     11 struct twosat
     12 {
     13     int n;
     14     vector<int> g[maxn*2];
     15     bool mark[maxn*2];
     16     int s[maxn*2],c;
     17     int ty[maxn];
     18     
     19     bool dfs(int x)
     20     {
     21         if (mark[x^1]) return false;
     22         if (mark[x]) return true;
     23         
     24         mark[x] = true;
     25         
     26         s[c++] = x;
     27         
     28         for (int i = 0;i < g[x].size();i++)
     29         {
     30             if (!dfs(g[x][i])) return false;
     31         }
     32         
     33         return true;
     34     }
     35     
     36     void add_clause(int x,int xval,int y,int yval)
     37     {
     38         x = x * 2 + xval;
     39         y = y * 2 + yval;
     40         
     41         g[x^1].push_back(y);
     42     }
     43     
     44     void init(int n)
     45     {
     46         this -> n = n;
     47         memset(mark,0,sizeof(mark));
     48         memset(ty,0,sizeof(ty));
     49         for (int i = 0;i <= n * 2;i++) g[i].clear(); 
     50     }
     51     
     52     bool solve()
     53     {
     54         for (int i = 0;i < n * 2;i += 2)
     55         {
     56             if (!mark[i] && !mark[i+1])
     57             {
     58                 c = 0;
     59                 
     60                 if (!dfs(i))
     61                 {
     62                     while (c > 0) mark[s[--c]] = 0;
     63                     if (!dfs(i+1)) return false;
     64                     else
     65                     {
     66                         while (c > 0) mark[s[--c]] = 0;
     67                         ty[i/2] = 2;
     68                     } 
     69                 }
     70                 else
     71                 {
     72                     while (c > 0) mark[s[--c]] = 0;
     73                     if (!dfs(i+1))
     74                     {
     75                         ty[i/2] = 1;
     76                         while (c > 0) mark[s[--c]] = 0;
     77                     }
     78                     else
     79                     {
     80                         ty[i/2] = 3;
     81                         while (c > 0) mark[s[--c]] = 0;
     82                     }
     83                 }
     84             }
     85             else
     86             {
     87                 if (mark[i]) ty[i/2] = 1;
     88                 else ty[i/2] = 2;
     89             }
     90         }
     91         
     92         return true;
     93     }
     94     
     95     /*void judge()
     96     {    
     97         for (int i = 0;i < n * 2;i += 2)
     98         {
     99             if (!mark[i] && !mark[i+1])
    100             {
    101                 c = 0;
    102                 
    103                 bool tr = 0;
    104                 bool fa = 0;
    105                 
    106                 if (dfs(i))
    107                 {
    108                     fa = 1;
    109                     while (c > 0) mark[s[--c]] = 0;
    110                 }
    111                 
    112                 if (dfs(i+1))
    113                 {
    114                     tr = 1;
    115                     while (c > 0) mark[s[--c]] = 0;
    116                 }
    117                 
    118                 if (tr && fa) ty[i/2] = 3;
    119                 else if (tr) ty[i/2] = 2;
    120                 else ty[i/2] = 1;
    121             }
    122             else
    123             {
    124                 //if (i == 0) printf("2333");
    125                 if (mark[i]) ty[i/2] = 1;
    126                 else ty[i/2] = 2;
    127             }
    128         }
    129     }*/
    130 }twosat;
    131 
    132 int main()
    133 {
    134     int n,m;
    135     int kase = 0;
    136     
    137     while (scanf("%d%d",&n,&m) != EOF)
    138     {
    139         if (n == 0 && m == 0) break;
    140         
    141         twosat.init(n);
    142         
    143         for (int i = 0;i < m;i++)
    144         {
    145             int k;
    146             scanf("%d",&k);
    147             
    148             int a[4];
    149             char ch[4][2];
    150             
    151             for (int j = 0;j < k;j++)
    152             {
    153                 scanf("%d%s",&a[j],ch[j]);
    154                 a[j]--;
    155             }
    156             
    157             //for (int j = 0;j < k;j++) vis[a[j]] = 1;
    158             
    159             if (k <= 2)
    160             {
    161                 for (int j = 0;j < k;j++)
    162                 {
    163                     if (ch[j][0] == 'y') twosat.add_clause(a[j],1,a[j],1);
    164                     else twosat.add_clause(a[j],0,a[j],0);
    165                 }
    166             }
    167             else
    168             {
    169                 bool b[4];
    170                 
    171                 for (int j = 0;j < k;j++)
    172                 {
    173                     b[j] = ch[j][0] == 'y' ? 1 : 0;
    174                 }
    175                 
    176                 for (int j = 0;j < k;j++)
    177                 {
    178                     for (int l = 0;l < k;l++)
    179                     {
    180                         if (j != l)
    181                         {
    182                             twosat.add_clause(a[j],b[j],a[l],b[l]);
    183                         }
    184                     }
    185                 }
    186             }
    187         }
    188         
    189         if (twosat.solve())
    190         {
    191             //twosat.judge();
    192             
    193             printf("Case %d: ",++kase);
    194             
    195             for (int i = 0;i < n;i++)
    196             {
    197                 switch(twosat.ty[i])
    198                 {
    199                     case 1 : printf("n");break;
    200                     case 2 : printf("y");break;
    201                     case 3 : printf("?");break;
    202                 }
    203             }
    204             printf("
    ");
    205         }
    206         else printf("Case %d: impossible
    ",++kase);
    207     }
    208     
    209     return 0;
    210 }
  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/kickit/p/8809230.html
Copyright © 2020-2023  润新知