zoukankan      html  css  js  c++  java
  • uva 11294 Wedding

    题意:

    一开始题读错了,囧,看了题解才发现,汗!

    有一对夫妻要结婚,他们坐在一条长凳上,这条长方形长凳有左右两端(自行脑补),来了若干对夫妻参加他们的婚礼。

    规定一对夫妻中的两个人不能坐在同一端。

    新娘因为头饰太复杂所以看不到跟她坐在同一侧的人。

    同时这些夫妻中有某些人存在不纯洁关系,新娘不希望同时看见有不纯结关系的两个人也就是说,存在不纯洁关系的两个人不能同时在新娘的对侧,但是可以同时坐在新娘的同侧。

    判断是否存在一个安排方案使得满足上述条件,如果存在,输出坐在新娘同侧的人,否则说明不可能。

    思路:

    2-SAT。

    首先假设新娘在左侧(假设右侧也可以,修改相关条件即可)

    把每个人看成一个点,那么假设坐在左侧为真,右侧为假。

    首先,对于每一对夫妻i和j,不能坐在同一侧,那么Xi和Xj不能同时为真,也不能同时为假,根据这两个限制条件就加两条边。

    其次,对于每一对有不纯洁关系的人,只要他们不同时坐在新娘的对侧就满足条件,只要Xi和Xj中至少一个为真即可,根据这个条件加边。

    要注意的一点是,因为新娘必须坐在新娘的同侧,所以一开始要把新娘赋值为真,因为新娘在左侧。

    输出的时候不输出新娘。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <vector>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 const int maxn = 200005;
      9 
     10 vector<int> ans;
     11 
     12 struct twosat
     13 {
     14     int n;
     15     vector<int> g[maxn*2];
     16     bool mark[maxn*2];
     17     int s[maxn*2],c;
     18     
     19     bool dfs(int x)
     20     {
     21         //printf("orz");
     22         if (mark[x^1]) return false;
     23         if (mark[x]) return true;
     24         
     25         mark[x] = true;
     26         
     27         s[c++] = x;
     28         
     29         for (int i = 0;i < g[x].size();i++)
     30         {
     31             if (!dfs(g[x][i])) return false;
     32         }
     33         
     34         return true;
     35     }
     36     
     37     void init(int n)
     38     {
     39         this -> n = n;
     40         for (int i = 0;i <= 2 * n;i++) g[i].clear();
     41         memset(mark,0,sizeof(mark));
     42     }
     43     
     44     void add_clause(int x,int xval,int y,int yval)
     45     {
     46         x = x * 2 + xval;
     47         y = y * 2 + yval;
     48         
     49         g[x^1].push_back(y);
     50         g[y^1].push_back(x);
     51     }
     52     
     53     bool solve()
     54     {
     55         for (int i = 0;i < 2 * n;i += 2)
     56         {
     57             if (!mark[i] && !mark[i+1])
     58             {
     59                 c = 0;
     60                 
     61                 if (!dfs(i))
     62                 {
     63                     while (c > 0) mark[s[--c]] = false;
     64                     if (!dfs(i+1)) return false;
     65                 }
     66             }
     67         }
     68         
     69         return true;
     70     }
     71 } twosat;
     72 
     73 int main()
     74 {
     75     int n,m;
     76     
     77     while (scanf("%d%d",&n,&m) != EOF)
     78     {
     79         if (n == 0 && m == 0) break;
     80         ans.clear();
     81         
     82         twosat.init(n * 2);
     83         
     84         for (int i = 0;i < n;i++)
     85         {
     86             twosat.add_clause(i,1,i+n,1);
     87             twosat.add_clause(i,0,i+n,0);
     88         }
     89         
     90         for (int i = 0;i < m;i++)
     91         {
     92             int a,b;
     93             char p[10],q[10];
     94             
     95             scanf("%d%s%d%s",&a,p,&b,q);
     96             
     97             if (p[0] == 'w') a += n;
     98             if (q[0] == 'w') b += n;
     99             
    100             twosat.add_clause(a,1,b,1);
    101             //twosat.add_clause(a,0,b,0);
    102         }
    103         
    104         twosat.mark[2 * n + 1] = 1;
    105         
    106         bool f = twosat.solve();
    107         
    108         if (f)
    109         {
    110             for (int i = 0;i < n * 2;i++)
    111             {
    112                 if (twosat.mark[2 * i + 1])
    113                 {
    114                     if (i == n) continue;
    115                     ans.push_back(i);
    116                 } 
    117             }
    118             
    119             if (ans[0] >= n)
    120             {
    121                 printf("%dw",ans[0]-n);
    122                 //printf("orz
    ");
    123             }
    124             else
    125             {
    126                 printf("%dh",ans[0]);
    127             }
    128             
    129             for (int i = 1;i < ans.size();i++)
    130             {
    131                 if (ans[i] >= n)
    132                 {
    133                     printf(" %dw",ans[i]-n);
    134                 }
    135                 else
    136                 {
    137                     printf(" %dh",ans[i]);
    138                 }
    139             }
    140         }
    141         else
    142         {
    143             printf("bad luck
    ");
    144         }
    145     }
    146     
    147     return 0;
    148 }
  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/kickit/p/8809240.html
Copyright © 2011-2022 走看看