• uvalive 3713 Astronauts


    题意:

    现在要安排一些宇航员去星球勘探。有3个星球,分别是J第一大的月亮A,J第二大的月亮B,S第一大的月亮C。

    规定年轻的宇航员不能去A,年长的宇航员不能去B,C任何人都可以去。

    现在有一些宇航员之间有矛盾,他们不能去相同的星球。

    现在问可否安排出这样的方案满足条件,如果有,那么就输出每个宇航员去的星球,没有就说明不可能。

    思路:

    2-SAT问题

    对于年轻的宇航员,去B为真,去C为假

    对于年长的宇航员,去A为真,去C为假

    首先考虑对于不同类型的宇航员i和j,只要他们不在同一个星球C上就满足条件,即Xi ∨ Xj为真就满足,利用这个条件加边

    但是对于同一个类型的宇航员i和j,他们不在同一个星球才满足条件,这个条件要求Xi 和Xj当中必定一个为真,一个为假,那么如何刻画呢?那就是两个当中至少一个为真,至少有一个为假,用符号表示即为Xi V Xj,┐Xi ∨┐Xj 两个条件同时为真,那么进行两次加边就可以了。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <vector>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 const int maxn = 100005;
      9 int a[maxn];
     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     
     18     bool dfs(int x)
     19     {
     20         if (mark[x^1]) return false;
     21         if (mark[x]) return true;
     22         
     23         mark[x] = true;
     24         
     25         s[c++] = x;
     26         
     27         for (int i = 0;i < g[x].size();i++)
     28         {
     29             if (!dfs(g[x][i])) return false;
     30         }
     31         
     32         return true;
     33     }
     34     
     35     void init(int n)
     36     {
     37         this -> n = n;
     38         
     39         for (int i = 0;i <= n * 2;i++) g[i].clear();
     40         
     41         memset(mark,0,sizeof(mark));
     42     }
     43     
     44     void add_clause(int x,int xval,int y,int yval)
     45     {
     46         x = 2 * x + xval;
     47         y = 2 * y + 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]] = 0;
     64                     
     65                     if (!dfs(i+1)) return false;
     66                 }
     67             }
     68         }
     69         
     70         return true;
     71     }
     72 } twosat;
     73 
     74 int main()
     75 {
     76     int n,m;
     77     //int kase = 0;
     78     
     79     while (scanf("%d%d",&n,&m) != EOF)
     80     {
     81         if (n == 0 && m == 0) break;
     82         
     83         int ave = 0;
     84         
     85         for (int i = 0;i < n;i++)
     86         {
     87             scanf("%d",&a[i]);
     88             ave += a[i];
     89         }
     90         
     91         //ave /= n;
     92         
     93         twosat.init(n);
     94         
     95         for (int i = 0;i < m;i++)
     96         {
     97             int x,y;
     98             
     99             scanf("%d%d",&x,&y);
    100             
    101             x--,y--;
    102             
    103             //if (x == y) continue;
    104             
    105             if (a[x] * n < ave && a[y] * n < ave)
    106             {
    107                 twosat.add_clause(x,1,y,1);
    108                 twosat.add_clause(x,0,y,0);
    109             }
    110             else if (a[x] * n >= ave && a[y] * n >= ave)
    111             {
    112                 twosat.add_clause(x,1,y,1);
    113                 twosat.add_clause(x,0,y,0);
    114             }
    115             else
    116             {
    117                 twosat.add_clause(x,1,y,1);
    118             }
    119         }
    120         
    121         if (twosat.solve())
    122         {
    123             for (int i = 0;i < n;i++)
    124             {
    125                 if (a[i] * n >= ave)
    126                 {
    127                     if (twosat.mark[2*i+1]) printf("A
    ");
    128                     else printf("C
    ");
    129                 }
    130                 else
    131                 {
    132                     if (twosat.mark[2*i+1]) printf("B
    ");
    133                     else printf("C
    ");
    134                 }
    135             }
    136         }
    137         else
    138         {
    139             printf("No solution.
    ");
    140         }
    141         
    142         //printf("
    ");
    143     }
    144     
    145     return 0;
    146 }
  • 相关阅读:
    ps_基于2020的官方教程
    杂记_好玩的
    linux _文件目录与权限
    levelDb笔记
    《好学的C++ 第2版》 第9章 一些高级编程技术
    《好学的C++ 第2版》 第8章 文件-电子存储
    《好学的C++ 第2版》 第7章 字符串--分析文本
    《好学的C++ 第2版》 第6章 指针--我知道数据在哪里
    《好学的C++ 第2版》 第5章 数组--都给我排好队
    《好学的C++ 第2版》 第4章 函数--分工与合作
  • 原文地址:https://www.cnblogs.com/kickit/p/8809207.html
Copyright © 2020-2023  润新知