题意:
和平委员会
根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。
此委员会必须满足下列条件:
- 每个党派都在委员会中恰有1个代表,
- 如果2个代表彼此厌恶,则他们不能都属于委员会。
每个党在议会中有2个代表。代表从1编号到2n。 编号为2i-1和2i的代表属于第I个党派。
任务
写一程序:
- 从文本文件读入党派的数量和关系不友好的代表对,
- 计算决定建立和平委员会是否可能,若行,则列出委员会的成员表,
- 结果写入文本文件。
输入
在文本文件的第一个行有2非负整数n和m。 他们各自表示:党派的数量n,1 < =n < =8000和不友好的代表对m,0 <=m <=20000。 在下面m行的每行为一对整数a,b,1<=a <b<=2n,中间用单个空格隔开。 它们表示代表a,b互相厌恶。
输出
如果委员会不能创立,文本文件中应该包括单词NIE。若能够成立,文本文件SPO.OUT中应该包括n个从区间1到2n选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。如果委员会能以多种方法形成,程序可以只写他们的某一个。
样品输入
3 2 1 3 2 4
样品输出
1 4 5分析:对于某个党两个代表只能选择一个,同时在厌恶的关系中的两个人只能有一个人存在,
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 using namespace std; 6 const int Maxn = 8000 * 2 + 10; 7 const int Maxm = 20000 * 2 + 10; //注意数据范围 8 struct Edge 9 { 10 int to, Next; 11 }edge[Maxm]; 12 int head[Maxn], tot; 13 void init() 14 { 15 tot = 0; 16 memset(head, -1, sizeof(head)); 17 } 18 void addedge(int u, int v) 19 { 20 edge[tot].to = v; 21 edge[tot].Next = head[u]; 22 head[u] = tot++; 23 } 24 bool vis[Maxn]; 25 int S[Maxn], top; 26 bool dfs(int u) 27 { 28 if (vis[u ^ 1]) 29 return false; 30 if (vis[u]) 31 return true; 32 vis[u] = true; 33 S[top++] = u; 34 for (int i = head[u]; i != -1; i = edge[i].Next) 35 if (!dfs(edge[i].to)) 36 return false; 37 return true; 38 } 39 bool Twosat(int n) 40 { 41 memset(vis, 0, sizeof(vis)); 42 for (int i = 0; i < n; i += 2) 43 { 44 if (vis[i] || vis[i ^ 1]) //已经选择了继续 45 continue; 46 top = 0; 47 if (!dfs(i)) 48 { 49 while (top) 50 vis[ S[--top] ] = false; 51 if (!dfs(i ^ 1)) 52 return false; 53 } 54 } 55 return true; 56 } 57 int main() 58 { 59 int n, m; 60 int u, v; 61 while (scanf("%d%d", &n, &m) != EOF) 62 { 63 init(); 64 while (m--) 65 { 66 scanf("%d%d", &u, &v); 67 u--; 68 v--; 69 addedge(u, v ^ 1); 70 addedge(v, u ^ 1); 71 } 72 if (Twosat(n * 2)) 73 { 74 for (int i = 0; i < 2 * n; i++) 75 if (vis[i]) 76 printf("%d\n", i + 1); 77 } 78 else printf("NIE\n"); 79 } 80 81 return 0; 82 }
时间: 2024-10-05 05:54:26