zoukankan      html  css  js  c++  java
  • UVA 11294 Wedding(2-sat)

    2-sat。不错的一道题,学到了不少。

    需要注意这么几点:

    1、题目中描述的是有n对夫妇,其中(n-1)对是来为余下的一对办婚礼的,所以新娘只有一位。

    2、2-sat问题是根据必然性建边,比如说A与B二选一,那么当不选A时,必然选B。在本题中,我们所能确定的必然性只有一种:当一对通奸者中的一个人出现在新娘的对面时,另一个必须在新娘的同侧。一开始,我每次建的是两条边,即由新娘指向对面的一人,再从这个人,指向与新娘同侧的另一人(语言描述较困难,但我尽量简明的表达出来)。这是一种假设,因为新娘既可能在左边,又可能在右边。但是这不是必然性:“新娘指向对面的一个人”,这条边不存在必然关系。

        解决办法:我们假定新娘就在某一侧。那么是否会影响最终结果呢?不会,因为不管在那一侧,只要有正确方案,转换一下方向,总归是成立的。

    3、如何确定新娘就在某一侧?

        建边的过程,我们假定了新娘的位置,但是并没有确定的在程序中表现出,新娘就在这一侧。

        方法:(1)mark[0]=1;明确的表示出新娘已被标记,但需要注意的是,每次dfs标记的是一条链,或者说是以你选择的点为根的一棵树,所以,只是这样做是不够的,需要单独对mark[0]做一次dfs。

                 (2)如代码中写的,dfs过程中,若是在 dfs(0) 时失败了,那么就return false;不给 dfs(1) 机会。

    注意:准确的说,确定了新娘的位置,即确定了“0w”和“0h”的位置,那么所有包含“0w”或“0h”的关系,所建的边都只能有一条。不过删掉约束条件一样能ac,仔细想来,是solve()中if(i==0)return false;的功劳,因为我只允许dfs(0)成功,所以即使建了另一条边,也不会有机会搜的。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<vector>
      5 #include<algorithm>
      6 using namespace std;
      7 
      8 const int MAXN=333;
      9 
     10 int n;
     11 bool mark[MAXN<<1];
     12 int S[MAXN<<1],c;
     13 vector<int >G[MAXN<<1];
     14 
     15 void init(int n)
     16 {
     17     for(int i=0;i<(n<<1);i++)
     18         G[i].clear();
     19     memset(mark,0,sizeof(mark));
     20 }
     21 
     22 void add(int x,int xval,int y,int yval)
     23 {
     24     x=(x<<1)+xval;
     25     y=(y<<1)+yval;
     26     G[x].push_back(y);
     27 }
     28 
     29 bool dfs(int x)
     30 {
     31     if(mark[x^1]){
     32         return false;
     33     }
     34     if(mark[x]){
     35         return true;
     36     }
     37     S[c++]=x;
     38     mark[x]=true;
     39     for(int i=0;i<G[x].size();i++)
     40     {
     41         if(!dfs(G[x][i])){
     42             return false;
     43         }
     44     }
     45     return true;
     46 }
     47 
     48 bool solve()
     49 {
     50     for(int i=0;i<(n<<1);i+=2)
     51     {
     52         if(!mark[i]&&!mark[i+1]){
     53             c=0;
     54             if(!dfs(i)){
     55                 if(i==0)      //如果新娘在 0 这一侧这一前提不成立,则 no solusion
     56                     return false;
     57                 while(c>0)
     58                     mark[S[--c]]=false;
     59                 if(!dfs(i+1))
     60                     return false;
     61             }
     62         }
     63     }
     64     return true;
     65 }
     66 
     67 int main()
     68 {
     69     int m,a,b;
     70     char x,y;
     71     while(~scanf("%d%d",&n,&m))
     72     {
     73         if(!n&&!m)
     74             return 0;
     75 
     76         init(n);
     77         for(int i=0;i<m;i++)           //固定新娘在 0 这一侧
     78         {
     79             scanf("%d%c %d%c",&a,&x,&b,&y);
     80             if(x=='h'&&y=='h'){
     81                 add(a,0,b,1);
     82                 add(b,0,a,1);
     83             }else if(x=='w'&&y=='w'){
     84                 add(a,1,b,0);
     85                 add(b,1,a,0);
     86             }else if(x=='h'&&y=='w'){
     87                 add(a,0,b,0);
     88                 add(b,1,a,1);
     89             }else if(x=='w'&&y=='h'){
     90                 add(a,1,b,1);
     91                 add(b,0,a,0);
     92             }
     93         }
     94         
     95         if(solve()){
     96             for(int i=1;i<n;i++)
     97             {
     98                 if(mark[i<<1])
     99                     printf("%dw",i);
    100                 else
    101                     printf("%dh",i);
    102                 if(i!=n-1)
    103                     printf(" ");
    104             }
    105             printf("
    ");
    106         }else
    107             printf("bad luck
    ");
    108     }
    109     return 0;
    110 }
    111 /*
    112 附上一组数据,让我发现了第三个问题
    113 10 10
    114 6h 2w
    115 1h 9w
    116 1w 3w
    117 9w 0h
    118 1h 9h
    119 4h 1w
    120 7h 2w
    121 1h 0h
    122 0h 9w
    123 0h 3h
    124 */
    View Code
  • 相关阅读:
    关于Web登陆安全
    HttpWebRequest 忽略证书
    C# 语音识别(文字to语音、语音to文字)
    Microsoft Visual Studio 11(ISO、Web Installer)、.NET Framework 4.5 等下载地址
    ubuntu硬盘安装及启动,menu.lst
    下载虾米音乐的歌词
    sublime text在linux下一键编译c和c++程序的配置文件
    foobar2000专辑封面混乱解决方法
    qt creator纯C或C++项目在windows下的命令行中文乱码解决
    婚姻就是嫁给习惯和性格(转)
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3244037.html
Copyright © 2011-2022 走看看