题目来源:POJ 2942 Knights of the Round Table

题意:统计多个个骑士不能參加随意一场会议 每场会议必须至少三个人 排成一个圈 而且相邻的人不能有矛盾 题目给出若干个条件表示2个人直接有矛盾

思路:求补图  能够坐在一起 就是能够相邻的人建一条边 然后假设在一个奇圈上的都是满足的 那些不再不论什么一个奇圈的就是不满足 求出全部奇圈上的点 总数减去它就是答案

首先有2个定理

1.一个点双连通分量是二分图 你就没有奇圈 假设有奇圈  那就不是二分图  充分必要条件 所以

2.一个点双连通分量有奇圈  那这个点双连通分量全部点都在奇圈上

所以这题就求点双连通分量 然后对每一个分量进行二分图判定 不是二分图 就把该双连通分量全部点都标记  标记是由于一个割点可能属于多个双连通分量

所以标记在求和

#include <vector>
#include <cstdio>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn = 1010;
struct Edge
{
int u, v;
Edge(){}
Edge(int u, int v): u(u), v(v){}
};
vector <int> a[maxn];
vector <int> bcc[maxn];
int pre[maxn];
int low[maxn];
int bccno[maxn];
int dfs_clock;
int bcc_cnt;
int bri;
int n, m;
int degree[maxn];
stack <int> S;
int A[maxn][maxn];
int odd[maxn];
int color[maxn];
bool bipartite(int u, int b)
{
for(int i = 0; i < a[u].size(); i++)
{
int v = a[u][i];
if(bccno[v] != b)
continue;
if(color[u] == color[v])
return false;
if(!color[v])
{
color[v] = 3 - color[u];
if(!bipartite(v, b))
return false;
}
}
return true;
}
void dfs(int u, int fa)
{
low[u] = pre[u] = ++dfs_clock;
S.push(u);
for(int i = 0; i < a[u].size(); i++)
{
int v = a[u][i];
if(v == fa)
continue;
if(!pre[v])
{
dfs(v, u);
low[u] = min(low[u], low[v]);
if(pre[u] <= low[v])
{
bcc_cnt++;
while(1)
{
int x = S.top(); S.pop();
bccno[x] = bcc_cnt;
bcc[bcc_cnt].push_back(x);
if(x == v)
{
bcc[bcc_cnt].push_back(u);
break;
}
}
}
}
else if(v != fa)
low[u] = min(low[u], pre[v]);
}
/*if(low[u] == pre[u])
{
bcc_cnt++;
while(1)
{
int x = S.top(); S.pop();
bccno[x] = bcc_cnt;
bcc[bcc_cnt].push_back(x);
if(x == u)
break;
}
}*/
}
void find_bcc()
{
memset(pre, 0, sizeof(pre));
memset(bccno, 0, sizeof(bccno));
dfs_clock = bcc_cnt = bri = 0;
for(int i = 1; i <= n; i++)
if(!pre[i])
dfs(i, -1);
}
int main()
{ while(scanf("%d %d", &n, &m) && (n||m))
{
memset(A, 0, sizeof(A));
while(m--)
{
int u, v;
scanf("%d %d", &u, &v);
A[u][v] = A[v][u] = 1;
}
for(int i = 0; i <= n; i++)
{
a[i].clear();
bcc[i].clear();
}
for(int i = 1; i <= n; i++)
for(int j = i+1; j <= n; j++)
{
if(A[i][j])
continue;
a[i].push_back(j);
a[j].push_back(i);
}
find_bcc();
memset(odd, 0, sizeof(odd));
for(int i = 1; i <= bcc_cnt; i++)
{
memset(color, 0, sizeof(color));
for(int j = 0; j < bcc[i].size(); j++)
bccno[bcc[i][j]] = i;
int u = bcc[i][0];
color[u] = 1;
if(!bipartite(u, i))
{
for(int j = 0; j < bcc[i].size(); j++)
odd[bcc[i][j]] = 1;
}
}
int ans = n;
for(int i = 1; i <= n; i++)
if(odd[i])
ans--;
printf("%d\n", ans);
}
return 0;
}

POJ 2942 Knights of the Round Table 黑白着色+点双连通分量的更多相关文章

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

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

  2. 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 ...

  3. POJ 2942 Knights of the Round Table

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

  4. POJ 2942 Knights of the Round Table - from lanshui_Yang

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

  5. poj 2942 Knights of the Round Table(点双连通分量+二分图判定)

    题目链接:http://poj.org/problem?id=2942 题意:n个骑士要举行圆桌会议,但是有些骑士相互仇视,必须满足以下两个条件才能举行: (1)任何两个互相仇视的骑士不能相邻,每个骑 ...

  6. POJ 2942 Knights of the Round Table (点双连通分量)

    题意:多个骑士要开会,3人及以上才能凑一桌,其中部分人已经互相讨厌,肯定不坐在同一桌的相邻位置,而且一桌只能奇数个人才能开台.给出多个人的互相讨厌图,要求多少人开不成会(注:会议不要求同时进行,一个人 ...

  7. poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)

    #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #includ ...

  8. POJ 2942 Knights of the Round Table(双连通分量)

    http://poj.org/problem?id=2942 题意 :n个骑士举行圆桌会议,每次会议应至少3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置.如果意见发生分歧,则需要举手表决,因此 ...

  9. POJ 2942.Knights of the Round Table (双连通)

    简要题解: 意在判断哪些点在一个图的  奇环的双连通分量内. tarjan求出所有的点双连通分量,再用二分图染色判断每个双连通分量是否形成了奇环,记录哪些点出现在内奇环内 输出没有在奇环内的点的数目 ...

随机推荐

  1. Day 14 python 之 字符串练习

    一.字符串总结与练习 #! /usr/bin/env python # -*- coding: utf-8 -*- # __author__ = "DaChao" # Date: ...

  2. js一段小代码(浏览器用alert,否则用console)

    (function(){ var root=this, isBrowserSide=false; if(typeof window !=="undefined" && ...

  3. (2)创建发布Maven

    一.创建maven项目 (1)命令行 mvn archetype:generate (2)选择模板默认是7 (3)输入组织号.项目名称及版本号.包名 回车确认 创建成功 二.转成idea项目 进入跟目 ...

  4. hdu6158(圆的反演)

    hdu6158 题意 初始有两个圆,按照标号去放圆,问放完 \(n\) 个圆后的总面积. 分析 圆的反演的应用. 参考blog 设反演圆心为 \(O\) 和反演半径 \(R\) 圆的反演的定义: 已知 ...

  5. error和exception的区别

    ------解决方法--------------------------------------------------------了解异常与错误的区别,并且知道当你截获一个异常时,应该怎么办.   ...

  6. POJ 1180 Batch Scheduling(斜率优化DP)

    [题目链接] http://poj.org/problem?id=1180 [题目大意] N个任务排成一个序列在一台机器上等待完成(顺序不得改变), 这N个任务被分成若干批,每批包含相邻的若干任务. ...

  7. xcode编译项目Permission denied错误

    打开终端,输入命令     sudo chmod -R 777 工作目录

  8. 如何移除inline-block元素之间的空白

    我们想要的是<li>元素可以紧贴在一起,但是很显然,结果“出乎意料”.那么有什么方法可以让结果符合我们的预期呢?所能想到的解决方法至少有以下四种,而每种方法也都有其优劣所在,至于要如何选择 ...

  9. debian6 安装VirtualBox的方法

    方法一: 参考: https://www.virtualbox.org/wiki/Linux_Downloads    更新sources.list deb http://download.virtu ...

  10. CAD中如何裁剪需要的区域

    M1: 先转换为块的方式进行裁剪 大范围框选复制出来>>B命令生成块>>XC命令>>选择刚才生成的块>>空格>>新边界>>框选新 ...