La3713 Astronauts 2-Sat
2016-07-20 20:11
387 查看
题目大意:
有A, B, C三个任务分配给n个宇航员, 其中每个宇航员要被分配一个任务。所有年龄大于平均年龄的宇航员可以选择A, C两种任务,其余人只能选择B, C两种任务, 同时这n个宇航员中有m组矛盾, i 和 j 之间矛盾表示 i 与 j 不能参与同一项任务。
问每个宇航员应如何分配任务。
分析:
本题是一个典型的2-Sat类型的题目,宇航员之间的矛盾有两种情况, 分别表示两个宇航员属于同一类型和不属于同一类型时候的选择,我们用真来表示选择A或B, 假来表示选择C, 那么当 i 和 j 两个宇航员属于同类时, 就说明 i 为真时 j 必定为假, 反之亦然。否则,只需要两者不同为假即可。
代码:
有A, B, C三个任务分配给n个宇航员, 其中每个宇航员要被分配一个任务。所有年龄大于平均年龄的宇航员可以选择A, C两种任务,其余人只能选择B, C两种任务, 同时这n个宇航员中有m组矛盾, i 和 j 之间矛盾表示 i 与 j 不能参与同一项任务。
问每个宇航员应如何分配任务。
分析:
本题是一个典型的2-Sat类型的题目,宇航员之间的矛盾有两种情况, 分别表示两个宇航员属于同一类型和不属于同一类型时候的选择,我们用真来表示选择A或B, 假来表示选择C, 那么当 i 和 j 两个宇航员属于同类时, 就说明 i 为真时 j 必定为假, 反之亦然。否则,只需要两者不同为假即可。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 100000 + 10; struct Twosat { int n; vector<int> G[maxn*2]; bool mark[maxn*2]; int S[maxn*2], c; void init(int n) { this->n = n; memset(mark, 0, sizeof(mark)); for(int i=0; i<2*n; i++) G[i].clear(); } bool dfs(int x) { if(mark[x^1]) return false; if(mark[x]) return true; mark[x] = true; S[c++] = x; for(int i=0; i<G[x].size(); i++) if(!dfs(G[x][i])) return false; return true; } //x = xval or y = yval void add_clause(int x, int xval, int y, int yval) { x = x*2 + xval; y = y*2 + yval; G[x^1].push_back(y); // when x != xval , y must = yval; G[y^1].push_back(x); // when y != yval , x must = xval; } bool solve() { for(int i=0; i<2*n; i+=2) if(!mark[i] && !mark[i^1]) { c = 0; if(!dfs(i)) { while(c > 0) mark[S[--c]] = false; if(!dfs(i^1)) return false; } } return true; } }solver; int n, m, u, v; bool type[maxn]; int age[maxn], age_sum; void init() { solver.init(n); age_sum = 0; memset(type, false, sizeof(type)); } int main() { #ifndef ONLINE_JUDGE freopen("data.txt", "r", stdin); freopen("ans.txt", "w", stdout); #endif while(scanf("%d%d", &n, &m) == 2 && n+m) { init(); for(int i=0; i<n; i++) { scanf("%d", &age[i]); age_sum += age[i]; } for(int i=0; i<n; i++) type[i] = (age[i] * n >= age_sum); for(int i=0; i<m; i++) { scanf("%d%d", &u, &v); u--, v--; if(type[u] == type[v]) solver.add_clause(u, 1, v, 1), solver.add_clause(u, 0, v, 0); else solver.add_clause(u, 1, v, 1); } if(!solver.solve()) printf("No solution.\n"); else { for(int i=0; i<n; i++) { if(solver.mark[i*2+1]) printf("%c\n", type[i] ? 'A' : 'B'); else printf("%c\n", 'C'); } } } return 0; }
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C 语言简单加减乘除运算
- C语言自动生成enum值和名字映射代码
- C语言练习题:自由落体的小球简单实例
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中进制知识汇总
- C语言判断一个数是否是2的幂次方或4的幂次方
- C语言二进制思想以及数据的存储
- C语言中计算正弦的相关函数总结