[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. netbackup :nbu备份 Hyper-V 遇到快照错误(状态码 156)

    遇到快照错误(状态码 156) 下表介绍与 NetBackup 状态码 156 有关的 Hyper-V 问题. 表:状态码 156 的可能原因 状态码 156 的原因 说明及推荐操作 NetBacku ...

  2. pymysql 简单操作数据库

    #!/usr/bin/env python #-*- coding:utf-8 -*- # author:leo # datetime:2019/4/24 15:22 # software: PyCh ...

  3. 手写promise

    写在前面: 在目前的前端分开中,我们对于异步方法的使用越来越频繁,那么如果处理异步方法的返回结果,如果优雅的进行异步处理对于一个合格的前端开发者而言就显得尤为重要,其中在面试中被问道最多的就是对Pro ...

  4. 常见react面试题汇总

    已经开源 地址:https://github.com/nanhupatar...关注我们团队: React 中 keys 的作用是什么? Keys 是 React 用于追踪哪些列表中元素被修改.被添加 ...

  5. thinkphp 5数据库操作

    1.原生sql $options=Db::table('__MALL_POST__') ->alias('m') ->join('__MALL_CATEGORY_VALUE__ v','m ...

  6. Linux 面试的一些基础命令

    1.查询服务器负载 (1)uptime [root@oldboy ~]# uptime 20:17:18 up 7:41, 2 users, load average: 0.00, 0.00, 0.0 ...

  7. 动态规划:HDU2159-FATE(二维费用的背包问题)

    FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  8. Word 2013发布博客测试

    Hello world ! I am from word2013! 测试修改 这里添加一行文字.   参考 1在 Word 中建立博客的相关帮助 2使用Word2013发布随笔到博客园 PS: 参考2 ...

  9. 批处理文件执行cmd命令

    @echo offstart "wumin" "C:\Windows\System32\cmd.exe" osk taskkill /f /im cmd.exe ...

  10. 2 Model层 -定义模型

    1  ORM简介 MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库 ORM是“对象-关系-映射” ...