LINK


题目大意

有一群人,其中有一些人之间有矛盾,现在要求选出一些人形成一个环,这个环要满足如下条件:

1.人数大于1

2.总人数是奇数

3.有矛盾的人不能相邻

问有多少人不能和任何人形成任何的环

思路

发现如果在原图上直接判断非常的不方便

考虑在补图上挖掘性质

补图:

补图和原图没有任何一条重边

不图和原图的所有边并集是一个完全图

即删去所有存在的边,把不存在的边加上

发现可以选出来的环在补图上一定是一个奇环

那么就可以考虑怎么找到补图中的所有奇环

  • 性质1:包含一个奇环的点双连通分量中的每一个点一定属于某一个奇环

这个性质还挺神奇的

因为这个点双联通分量中的每两个点之间至少有两条点不相交路径

所以假设一个偶环包含了一个奇环中的一部分\(p_u...p_v\),

因为p是奇环所以\(p_u\)到\(p_v\)中一定有一条长度是奇数的路径和一条长度是偶数的路径

所以结论成立咯

所以就可以发现只需要对每个强连通分量判断包不包含奇环就可以了

  • 性质2:包含奇环的充分必要条件是二分图染色冲突

还挺好证明的吧

如果二分图染色不出现冲突,就是个二分图了

二分图中是没有奇环的

所以直接点双联通判一下有没有奇环就可以了


毒瘤poj上有多组数据

注意清零的问题

特别是二分图染色的数组


//Author: dream_maker
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e3 + 10;
const int M = 1e6 + 10;
struct Edge{
int u, v, nxt;
} E[M << 1];
int g[N][N], n, m, in[N];
int head[N], tot, vis[N], col[N];
void add(int u, int v) {
++tot;
E[tot].u = u;
E[tot].v = v;
E[tot].nxt = head[u];
head[u] = tot;
}
void clean() {
memset(head, 0, sizeof(head));
tot = 0;
}
bool dfs(int u, int now) {
col[u] = now;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (!in[v]) continue;
if (col[v] && col[v] == col[u]) return 1;
else if (!col[v] && dfs(v, 3 - now)) return 1;
}
return 0;
}
namespace Tarjan {
int dfn[N], low[N], bel[N];
int ind = 0, cnt_bcc = 0;
stack<Edge> st;
vector<int> bcc[N];
void init() {
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(bel, 0, sizeof(bel));
ind = 0;
}
void tarjan(int u, int fa) {
dfn[u] = low[u] = ++ind;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa) continue;
if (!dfn[v]) {
st.push(E[i]);
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) {
++cnt_bcc;
bcc[cnt_bcc].clear();
Edge now;
do {
now = st.top(); st.pop();
if (bel[now.u] != cnt_bcc) {
bel[now.u] = cnt_bcc;
bcc[cnt_bcc].push_back(now.u);
}
if (bel[now.v] != cnt_bcc) {
bel[now.v] = cnt_bcc;
bcc[cnt_bcc].push_back(now.v);
}
} while (now.u != u || now.v != v);
fv(j, bcc[cnt_bcc]) in[bcc[cnt_bcc][j]] = 1;
if (dfs(bcc[cnt_bcc][0], 1))
fv(j, bcc[cnt_bcc]) vis[bcc[cnt_bcc][j]] = 1;
fv(j, bcc[cnt_bcc]) in[bcc[cnt_bcc][j]] = col[bcc[cnt_bcc][j]] = 0;
}
} else {
if (dfn[v] < dfn[u]) {
st.push(E[i]);
low[u] = min(low[u], dfn[v]);
}
}
}
}
}
using namespace Tarjan;
int main() {
freopen("input.txt", "r", stdin);
while (1) {
Read(n), Read(m);
if (!n && !m) return 0;
tot = 0;
fu(i, 1, n) head[i] = vis[i] = 0;
init();
fu(i, 1, n)
fu(j, 1, n)
g[i][j] = (i == j);
fu(i, 1, m) {
int u, v; Read(u), Read(v);
g[u][v] = g[v][u] = 1;
}
fu(i, 1, n)
fu(j, 1, n)
if (!g[i][j])
add(i, j);
fu(i, 1, n) if (!dfn[i]) tarjan(i, 0);
int ans = n;
fu(i, 1, n) if (vis[i]) --ans;
Write(ans), putchar('\n');
}
return 0;
}

POJ2942 Knights of the Round Table【Tarjan点双联通分量】【二分图染色】【补图】的更多相关文章

  1. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

  2. POJ2942 Knights of the Round Table(点双连通分量 + 二分图染色)

    题目大概说要让n个骑士坐成一圈,这一圈的人数要是奇数且大于2,此外有些骑士之间有仇恨不能坐在一起,问有多少个骑士不能入座. 双连通图上任意两点间都有两条不重复点的路径,即一个环.那么,把骑士看做点,相 ...

  3. POJ 2942 Knights of the Round Table 补图+tarjan求点双联通分量+二分图染色+debug

    题面还好,就不描述了 重点说题解: 由于仇恨关系不好处理,所以可以搞补图存不仇恨关系, 如果一个桌子上面的人能坐到一起,显然他们满足能构成一个环 所以跑点双联通分量 求点双联通分量我用的是向栈中pus ...

  4. UVA 1364 - Knights of the Round Table (获得双连接组件 + 二部图推理染色)

    尤其是不要谈了些什么,我想A这个问题! FML啊.....! 题意来自 kuangbin: 亚瑟王要在圆桌上召开骑士会议.为了不引发骑士之间的冲突. 而且可以让会议的议题有令人惬意的结果,每次开会前都 ...

  5. poj 2942 Knights of the Round Table - Tarjan

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

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

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

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

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

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

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

  9. Spoj 2878 KNIGHTS - Knights of the Round Table | 双联通分量 二分图判定

    题目链接 考虑建立原图的补图,即如果两个骑士不互相憎恨,就在他们之间连一条无向边. 显而易见的是,如果若干个骑士在同一个点数为奇数的环上时,他们就可以在一起开会.换句话说,如果一个骑士被一个奇环包含, ...

随机推荐

  1. Qt emit的使用

    1. 假设现在我定义了一个类A,现在想在A的一个函数void A::function1()当中的结尾处emit一个信号signal1(),然后利用这个信号触发另一个类B进行某项操作void B::fu ...

  2. uva 1048 最短路的建图 (巧,精品)

    大白书 P341这题说的是给了NT种飞机票,给了价钱和整个途径,给了nI条要旅游的路线.使用飞机票都必须从头第一站开始坐,可以再这个路径上的任何一点下飞机一但下飞机了就不能再上飞机,只能重新买票,对于 ...

  3. nginx重启 failed (98: Address already in use)

    启动nginx服务,无法正常启动,一查log日志,发现如题错误信息. 问题描述:地址已被使用.可能nginx服务卡死了,导致端口占用,出现此错误. 查看端口 netstat -ntpl 杀掉进程   ...

  4. 怎样在linux下对U盘进行格式化和分区

    说明,为了不做无用功,首先必须卸载要分区的设备,分区才能执行成功.通过命令umount /media/?? 或者umount /mnt/??? 看你的实际情况,这一步必不可少.1.首先通过命令fdis ...

  5. SQL学习笔记四(补充-1-1)之MySQL单表查询补充部分:SQL逻辑查询语句执行顺序

    阅读目录 一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析 一 SELECT语句关键字的定义顺序 SELE ...

  6. js 变量、函数提升 与js的预编译有关

    参考网址:http://www.codesec.net/view/178491.html 先简单理解下作用域的概念,方便对变量与函数提升的概念的理解 function foo() { var x = ...

  7. windows下利用批处理脚本监控程序

    1.要监控的程序为使用cygwin环境编译的exe可执行文件hello.exe,源码如下: #include <stdio.h> #include <unistd.h> voi ...

  8. HDU 6438 网络赛 Buy and Resell(贪心 + 优先队列)题解

    思路:维护一个递增队列,如果当天的w比队首大,那么我们给收益增加 w - q.top(),这里的意思可以理解为w对总收益的贡献而不是真正获利的具体数额,这样我们就能求出最大收益.注意一下,如果w对收益 ...

  9. Lucene 基础知识

    1. 数据分类 结构化数据: 指具有固定格式或有限长度的数据,如数据库等; 非结构化数据: 指不定长或无固定格式的数据, 如邮件,word 文档等磁盘上的文件; 1.1 非结构化数据查询方法 顺序扫描 ...

  10. 如何识别网页类型(wap页面还是wise页面)

    思路很简单,就是通过网页结构的一些特征来区分,当然也可以通过url的格式来区分,不过这个错误率较高,因为有很多小网站的url设计不规范. 网页特征包括两大类: 1.meta信息: 一般wap页面都会为 ...