[POJ2942][LA3523]Knights of the Round Table

试题描述

Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the other knights are fun things to do. Therefore, it is not very surprising that in recent years the kingdom of King Arthur has experienced an unprecedented increase in the number of knights. There are so many knights now, that it is very rare that every Knight of the Round Table can come at the same time to Camelot and sit around the round table; usually only a small group of the knights isthere, while the rest are busy doing heroic deeds around the country.

Knights can easily get over-excited during discussions-especially after a couple of drinks. After some unfortunate accidents, King Arthur asked the famous wizard Merlin to make sure that in the future no fights break out between the knights. After studying the problem carefully, Merlin realized that the fights can only be prevented if the knights are seated according to the following two rules:

  • The knights should be seated such that two knights who hate each other should not be neighbors at the table. (Merlin has a list that says who hates whom.) The knights are sitting around a roundtable, thus every knight has exactly two neighbors.

  • An odd number of knights should sit around the table. This ensures that if the knights cannot agree on something, then they can settle the issue by voting. (If the number of knights is even, then itcan happen that yes and no have the same number of votes, and the argument goes on.)

Merlin will let the knights sit down only if these two rules are satisfied, otherwise he cancels the meeting. (If only one knight shows up, then the meeting is canceled as well, as one person cannot sit around a table.) Merlin realized that this means that there can be knights who cannot be part of any seating arrangements that respect these rules, and these knights will never be able to sit at the Round Table (one such case is if a knight hates every other knight, but there are many other possible reasons). If a knight cannot sit at the Round Table, then he cannot be a member of the Knights of the Round Table and must be expelled from the order. These knights have to be transferred to a less-prestigious order, such as the Knights of the Square Table, the Knights of the Octagonal Table, or the Knights of the Banana-Shaped Table. To help Merlin, you have to write a program that will determine the number of knights that must be expelled.

\(n\) 个骑士经常参加圆桌会议,一次会议需要选多于一个骑士坐在一张圆桌旁,并且需要满足:

  • 互相憎恨的骑士不能坐在相邻位置;

  • 圆桌旁有奇数个骑士。

问有多少个骑士不能参加任何会议。

输入

The input contains several blocks of test cases. Each case begins with a line containing two integers \(1 \le n \le 1000\) and \(1 \le m \le 1000000\) . The number n is the number of knights. The next \(m\) lines describe which knight hates which knight. Each of these m lines contains two integers \(k_1\) and \(k_2\) , which means that knight number \(k_1\) and knight number \(k_2\) hate each other (the numbers \(k_1\) and \(k_2\) are between \(1\) and \(n\) ).

The input is terminated by a block with n = m = 0 .

输出

For each test case you have to output a single integer on a separate line: the number of knights that have to be expelled.

输入示例

5 5
1 4
1 5
2 5
3 4
4 5
0 0

输出示例

2

数据规模及约定

见“输入

题解

注意这题是-双连通分量。(判断是边双还是点双,画几个“8 字形”就好了)

我们将所有的点双依次处理(割点一定要被处理多次,它属于多个点双),看每个点双是否能被二分图染色,不能被二分染色的点双中所有点是可以参加圆桌会议的。

我们可以证明如果一个点双中含有一个简单奇环,那么该双连通分量中所有点都可以在某个简单奇环中。读者不妨自己画一个有交(指边同时在两个环中)奇环和偶环,发现偶环上所有点都可以将它所在偶环的那一半和奇环的一半拼出一个大奇环。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;
#define rep(i, s, t) for(int i = (s); i <= (t); i++)
#define dwn(i, s, t) for(int i = (s); i >= (t); i--) const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 1010
#define maxm 2000010 struct Edge {
int a, b;
Edge() {}
Edge(int _, int __): a(_), b(__) {}
} es[maxm];
int n, m, head[maxn], nxt[maxm];
bool G[maxn][maxn]; void AddEdge(int a, int b) {
es[++m] = Edge(a, b); nxt[m] = head[a]; head[a] = m;
swap(a, b);
es[++m] = Edge(a, b); nxt[m] = head[a]; head[a] = m;
return ;
} int clo, dfn[maxn], low[maxn], bcno[maxn], cntb, top;
Edge S[maxm];
vector <int> bcc[maxn];
bool iscut[maxn];
void dfs(int u, int fa) {
dfn[u] = low[u] = ++clo;
int ch = 0;
for(int i = head[u]; i; i = nxt[i]) if(i != fa) {
Edge& e = es[i];
if(dfn[e.b]) low[u] = min(low[u], dfn[e.b]);
else {
S[++top] = e;
dfs(e.b, i); ch++;
low[u] = min(low[u], low[e.b]);
if(low[e.b] >= dfn[u]) {
iscut[u] = 1;
cntb++;
while(1) {
Edge s = S[top--];
if(bcno[s.a] != cntb) bcno[s.a] = cntb, bcc[cntb].push_back(s.a);
if(bcno[s.b] != cntb) bcno[s.b] = cntb, bcc[cntb].push_back(s.b);
if(s.a == e.a && s.b == e.b) break;
}
}
}
}
if(!fa && ch == 1) iscut[u] = 0;
return ;
} bool cant[maxn];
int col[maxn];
bool solve(int u, int b, int c) {
if(col[u]) return col[u] == c;
col[u] = c;
for(int i = head[u]; i; i = nxt[i]) {
Edge& e = es[i];
if(bcno[e.b] == bcno[u] && !solve(e.b, b, 3 - c)) return 0;
}
return 1;
} int main() {
while(1) {
n = read(); int M = read();
if(!n) break; memset(G, 0, sizeof(G));
rep(i, 1, M) {
int a = read(), b = read();
G[a][b] = G[b][a] = 1;
} m = 0; memset(head, 0, sizeof(head));
rep(i, 1, n)
rep(j, i + 1, n) if(!G[i][j]) AddEdge(i, j); memset(dfn, 0, sizeof(dfn)); clo = 0;
memset(low, 0, sizeof(low));
memset(bcno, 0, sizeof(bcno));
rep(i, 1, cntb) bcc[i].clear();
cntb = 0;
rep(i, 1, n) if(!dfn[i]) dfs(i, 0);
/*printf("cntb: %d\n", cntb);
rep(i, 1, cntb) {
printf("%d:", i);
for(vector <int> :: iterator j = bcc[i].begin(); j != bcc[i].end(); j++)
printf(" %d", *j);
putchar('\n');
}*/ memset(cant, 0, sizeof(cant));
rep(i, 1, cntb) {
for(vector <int> :: iterator j = bcc[i].begin(); j != bcc[i].end(); j++)
bcno[*j] = i;
memset(col, 0, sizeof(col));
if(!solve(*bcc[i].begin(), i, 1))
for(vector <int> :: iterator j = bcc[i].begin(); j != bcc[i].end(); j++)
cant[*j] = 1;
} int cnt = n;
rep(i, 1, n) cnt -= cant[i];
printf("%d\n", cnt);
} return 0;
}

[POJ2942][LA3523]Knights of the Round Table的更多相关文章

  1. POJ2942 UVA1364 Knights of the Round Table 圆桌骑士

    POJ2942 洛谷UVA1364(博主没有翻墙uva实在是太慢了) 以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则 ...

  2. 【poj2942】 Knights of the Round Table

    http://poj.org/problem?id=2942 (题目链接) 题意 有n个骑士要去参加圆桌会议,他们将围成一圈,想要他们不打架,当且仅当参加圆桌会议的骑士数为奇数并且相邻的两个骑士不互相 ...

  3. POJ2942:Knights of the Round Table——题解

    http://poj.org/problem?id=2942 所写的tarjan练习题最难的一道. 说白了难在考得不是纯tarjan. 首先我们把仇恨关系处理成非仇恨关系的图,然后找双连通分量,在双连 ...

  4. 【POJ2942】Knights of the Round Table(二分图 点双联通分量)

    题目链接 大意 给定\(N\)个点与\(M\)个关系,每个关系表示某两个点间没有直接的边相连,求不在所有奇环上的点的个数. (\(1\le N\le 1e3,1\le M\le 1e6\)) 思路 考 ...

  5. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  6. 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)

    Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress ...

  7. 「题解」:[POJ2942]Knights of the Round Table

    问题 E: Knights of the Round Table 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 作为一名骑士是一个非常有吸引力的职业:寻找圣杯,拯救遇难的少女,与 ...

  8. POJ 2942 Knights of the Round Table

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 10911   Acce ...

  9. poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 9169   Accep ...

随机推荐

  1. 2018.6.21 css的应用---注册表格

    参与css样式表格的注册表单 <!DOCTYPE html> <head> <meta charset="UTF-8" /> <meta ...

  2. 解决centos7 nslookup:command not found

    解析域名www.google.com时,报错,命令找不到,是因为新安装的centos7,没有安装bind-utils,安装后就可以运行nslookup了

  3. 分享12款最佳的Bootstrap设计工具

    设计师总会渴望有一些新奇有趣的设计工具来提高工作效率,而Bootstrap就是您的不二选择.2013年Bootstrap得到了广泛普及, 它是开发者较为常用的框架之一,本文我们将分享12款最佳的Boo ...

  4. iOS 中push和pop到底系统做了些什么事

    iOS中的push和pop是一个很常用的视图切换方法,他们是成对出现的, 简而言之,push就是压栈,pop就是出栈! [self.navigationController pushViewContr ...

  5. 第三篇、Swift基础学习

    1.常量与变量 什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 变量的 ...

  6. 【原创】数据处理中判断空值的方法(np.isnan、is np.nan和pd.isna)比较

      转载请注明出处:https://www.cnblogs.com/oceanicstar/p/10869725.html  1.np.isnan(只有数组数值运算时可使用) 注意:numpy模块的i ...

  7. 【前端_js】ajax的应用

    1.设置请求头部 function makeRequest() { alert("inside makeRequest()"); var settings = { type: &q ...

  8. javascript 计算倒计时

    function timeDown(second) { var month = '', day = '', hour = '', minute = ''; if (second >= 86400 ...

  9. 笔记1 python入门学习笔记

    目录 官方手册 菜鸟站手册地址: python的运行方法 注释 小技巧: input()接收用户输入的内容(默认为字符串) print() 运算符 is 是判断两个标识符是不是引用自一个对象 all和 ...

  10. String java问题随笔

    1.字符串加密 设计思想: 每个字符都能够转化为整数型,也能将整数型转化为字符类型,这样我们在加密时候由于向后推3个,所以可以将字符转换为整形,然后加3,之后在将运算完的变量转化为字符后输出,就可以实 ...