[POJ2942][LA3523]Knights of the Round Table
[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
andno
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的更多相关文章
- POJ2942 UVA1364 Knights of the Round Table 圆桌骑士
POJ2942 洛谷UVA1364(博主没有翻墙uva实在是太慢了) 以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则 ...
- 【poj2942】 Knights of the Round Table
http://poj.org/problem?id=2942 (题目链接) 题意 有n个骑士要去参加圆桌会议,他们将围成一圈,想要他们不打架,当且仅当参加圆桌会议的骑士数为奇数并且相邻的两个骑士不互相 ...
- POJ2942:Knights of the Round Table——题解
http://poj.org/problem?id=2942 所写的tarjan练习题最难的一道. 说白了难在考得不是纯tarjan. 首先我们把仇恨关系处理成非仇恨关系的图,然后找双连通分量,在双连 ...
- 【POJ2942】Knights of the Round Table(二分图 点双联通分量)
题目链接 大意 给定\(N\)个点与\(M\)个关系,每个关系表示某两个点间没有直接的边相连,求不在所有奇环上的点的个数. (\(1\le N\le 1e3,1\le M\le 1e6\)) 思路 考 ...
- POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 12439 Acce ...
- 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)
Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress ...
- 「题解」:[POJ2942]Knights of the Round Table
问题 E: Knights of the Round Table 时间限制: 1 Sec 内存限制: 256 MB 题面 题目描述 作为一名骑士是一个非常有吸引力的职业:寻找圣杯,拯救遇难的少女,与 ...
- POJ 2942 Knights of the Round Table
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 10911 Acce ...
- poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 9169 Accep ...
随机推荐
- python_25_string
name="my name is 齐志光qizhiguang" print(name.capitalize())#首字母变大写 print(name.count('i'))#统计字 ...
- kubernetes-存储卷(十二)
为了保证数据的持久性,必须保证数据在外部存储在docker容器中,为了实现数据的持久性存储,在宿主机和容器内做映射,可以保证在容器的生命周期结束,数据依旧可以实现持久性存储.但是在k8s中,由于pod ...
- SQLServer事务的原理
1.事务的概念 是数据库管理系统执行过程中的一个逻辑单元,由一个有限的数据库操作序列组成: 由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操 ...
- C# 理解FileInfo类的Open()方法
我们在对文件进行读写操作之前必须打开文件,FileInfo类为我们提供了一个Open()方法,该方法包含了两个枚举类型值的参数,一个为FileMode枚举类型值,另一个为FileAccess枚举类型值 ...
- java面向对象思想2
1.主函数是一类特殊的函数,作为程序入口,可被虚拟机调用.主函数格式是固定的.public:函数访问权限最大.static:代表函数随着类的加载已经存在.void:主函数没有具体返回值.main:不是 ...
- 洛谷P1111修复公路并查集改
看了他们的题解感觉很震惊,为什么要用kruskal,这题要用到最小生成树吗??? 38行短短的程序就可以了,我觉得学习不是一种套用,套自己学的,而且题解很大一部分都是kruskal. 个人认为自己的程 ...
- mysql update 多表关联更新
UPDATE new_schedules_spider_static_schedule s join new_scac_port p on p.`PORT` = s.`PORT` and p.SCAC ...
- 项目实战14.1—ELK 企业内部日志分析系统
本文收录在Linux运维企业架构实战系列 一.els.elk 的介绍 1.els,elk els:ElasticSearch,Logstash,Kibana,Beats elk:ElasticSear ...
- Python基础:输入与输出(I/O)
来做一个NLP任务 步骤为: 1.读取文件: 2.去除所有标点符号和换行符,并把所有大写变成小写: 3.合并相同的词,统计每个词出现的频率,并按照词频从大到小排序: 4.将结果按行输出到文件 out. ...
- Diycode开源项目 NodeListFragment分析
1.整体分析 1.1.作用讲解 这个类没有用到,只是一个备用的. 分类列表,用于定制首页内容 考虑到节点列表一般不会变化,所以直接将数据封装在客户端中,可以直接查看,提高效率. 1.2.整体分析 首先 ...