题意:

现在要安排一些宇航员去星球勘探。有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\n");
128                     else printf("C\n");
129                 }
130                 else
131                 {
132                     if (twosat.mark[2*i+1]) printf("B\n");
133                     else printf("C\n");
134                 }
135             }
136         }
137         else
138         {
139             printf("No solution.\n");
140         }
141
142         //printf("\n");
143     }
144
145     return 0;
146 }

转载于:https://www.cnblogs.com/kickit/p/8809207.html

uvalive 3713 Astronauts相关推荐

  1. 训练指南 UVALive - 3713 (2-SAT)

    layout: post title: 训练指南 UVALive - 3713 (2-SAT) author: "luowentaoaa" catalog: true mathja ...

  2. uvaLive 3713

    题目链接 #include <cstdio> #include <cstring> #include <vector> using namespace std; # ...

  3. uvalive 3713 2-sat

    /** 分析:训练指南图论例题10,p327 2-sat **/#include <iostream> #include <cstdio> #include <cstri ...

  4. 图论算法与模型(训练指南题库)

    一.基础题目 1.UVA 11624 Fire!迷宫问题 多源BFS 题意: 帮助joe走出一个大火蔓延的迷宫,其中joe每分钟可往上下左右四个方向之一走,所有着火的格子都会蔓延(空格与着火格有公共边 ...

  5. DP UVALive 6506 Padovan Sequence

    题目传送门 /*题意:两行数字,相邻列一上一下,或者隔一列两行都可以,从左到右选择数字使和最大DP:状态转移方程:dp[i][j] = max (dp[i][j], dp[1-i][j-1] + a[ ...

  6. The UVALIVE 7716 二维区间第k小

    The UVALIVE 7716 二维区间第k小 /** 题意:给一个n * n的矩阵,有q个查询每次查询r,c,s,k表示已(r,c)为右上角 大小为s的正方形中 第k小的元素n <= 250 ...

  7. UVALive 8513 lovers 2017 西安区域赛 B 贪心+multiset

    UVALive 8513 有2种人,每个人有自己的权值$A_i$ $B_i$ 当$A_i + B_i >=K$时 两个人可以配对 问最多多少人可以配对 解法 : 把$/{ A_i /}$ 排序 ...

  8. 逆序数 UVALive 6508 Permutation Graphs

    题目传送门 1 /* 2 题意:给了两行的数字,相同的数字连线,问中间交点的个数 3 逆序数:第一行保存每个数字的位置,第二行保存该数字在第一行的位置,接下来就是对它求逆序数 4 用归并排序或线段树求 ...

  9. Infinite Fraction Path UVALive - 8207

    Infinite Fraction Path UVALive - 8207 题意: 给你n个数,每个数在0到9之间,每个数的下标一次是0~n-1,然后他所能走到的数为(i^2+1)%n,i为他本身的下 ...

  10. F - Heron and His Triangle UVALive - 8206

    F - Heron and His Triangle UVALive - 8206 题意: 给你应该n,然后求一个最小的t,问长度为t-1,t,t+1所组成的三角形的面积为整数,t>=n 题解: ...

最新文章

  1. Spring的控制反转(IOC)和依赖注入(DI)具体解释
  2. yolov3-tf2 数据格式压缩
  3. Hadoop 面试题之Hbase
  4. stand up meeting 12/8/2015
  5. 微服务~Eureka实现的服务注册与发现及服务之间的调用
  6. pycharm中无法识别相对路径的问题
  7. 单片机片外程序存储器数据存储器操作命令
  8. 支付宝最不想看到的:当“集五福”变成赚钱生意 有人日入千元!
  9. python语言磁力搜索引擎源码公开,基于DHT协议,十二分有技术含量的技术博客...
  10. mysql查询,left join(求并集),where(求交集)
  11. 基于html5的网上订餐系统,基于WEB的网上订餐系统-任务书.doc
  12. Vue中<keep-alive>组件的使用
  13. UDP进程terminated
  14. 基于matlab的车牌定位算法设计与实现,原创】基于matlab的汽车牌照识别系统设计与实现...
  15. MAC下微信双开(一键命令)
  16. 怎么制作书单视频?一款好用的制作软件教程
  17. [论文阅读笔记14]Nested named entity recognition revisited
  18. 开源项目:BottomBar
  19. 1325208-25-0,Mal-PEG4-NHS马来酰亚胺基团和NHS酯基团交联剂
  20. CDN里面的一些名词你知道是什么意思吗?

热门文章

  1. Ubuntu安装Google拼音
  2. Geth私链的多节点运行
  3. [办公自动化]目录修改以及插入分页符后行间距自动变宽
  4. 【知识向】——计算机基础知识总结及相关
  5. 彻底清除微软拼音输入法
  6. 作为股权类投资人,我们的投资偏好和投资原则
  7. 虚拟机超线程性能分析深入浅出
  8. linux 目录配额,详细讲解linux磁盘配额之Quota命令
  9. 金仓数据库KingbaseES blob类型数据导入导出
  10. 在项目中怎样写故障树或者类层次