[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
yesandnohave 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 ...
随机推荐
- 【luogu P3609 [USACO17JAN]Hoof, Paper, Scissor蹄子剪刀布】 题解
题目链接:https://www.luogu.org/problemnew/show/P3609 ### 看着标签什么记搜什么暴力点进来,读完题第一直觉DP? 还真是个\(DP\). 题目所描述的状态 ...
- Vue之Vue-touch的使用
最近项目中,有的页面发现设置返回键看起来怪怪的,感觉与整体不协调,于是就考虑使用手势滑动事件来实现返回功能~ 开叉查阅资料~找到了vue-touch,使用起来可谓是简单粗暴啊,适合我这样的快速开发人员 ...
- 20180909 解析JS Cookie的设置,获取和检索
引用: JavaScript Cookie - by runoob.com Cookie是储存在电脑文本文件中的数据,用于保存访问者的信息,并可以在下次打开页面时引用. 页面在设置/引用访问者信息时, ...
- display :inline-block 处理点小障碍
使用inline-block之前先处理点小障碍:inline-block元素会有4px左右的空隙,这个是因为我们写代码时候的换行符所致. 解决办法很简单:在inline-block的父元素中设置样式f ...
- 散列表的ASL计算
题目: 已知关键字序列为{30,25,72,38,8,17,59},设散列表表长为15.散列函数是H(key)=key MOD 13,处理冲突的方法为二次探测法Hi= ( H(key) + di )m ...
- popen和pclose详解及实例
popen函数是标准c提供的一个管道创建函数,其内部操作主 要是创建一个管道,调用fork创建子进程,关闭不需用的文件描述符,调用exec函数族执行popen的第一个参数.然后等到关闭. 也就是说我们 ...
- Atlas 配置高可用
keepalived安装 #下载keepalived ./configure --prefix=/usr/local Make && make install Atlas主安装keep ...
- 【前端_js】Chrome禁止缓存的方法
在前端开发中,浏览器缓存使得我们改了代码后页面不变,得经常手动清理缓存. 1.按如下操作即可禁用浏览器缓存, 这种方法基本能够做到完全禁止缓存,然而缺点是必须要将开发模式一直打开,占用屏幕空间.而且, ...
- mysql 复制一列到另一列
https://www.cnblogs.com/clphp/p/6251469.html
- iftop工具指令选项记录
iftop是实时监控网卡流量的工具,功能十分强大,指令选项非常多,用法比较复杂,下面记录一下命令的选择作用 相关参数及说明 1.iftop界面相关说明 界面上面显示的是类似刻度尺的刻度范围,为显示流量 ...