题意:有N个人要参加会议,围圈而坐,需要举手表决,所以每次会议都必须是奇数个人参加。有M对人互相讨厌,他们的座位不能相邻。问有多少人任意一场会议都不能出席。

分析:给出的M条关系是讨厌,将每个人视作点,在没有讨厌关系的人之间连边。

问题中很重要的一点是:任意一场会议都不能参加。能够参加某一场会议就意味着,参加会议的人可以构成一个奇回路(他们要围圈而坐,且必须出席奇数个人)。那么问题就转化成了求有多少个点不在任意一个奇回路中。

简单圈上的所有结点都属于同一个点双连通分量,因此找出所有的点双连通分量,并对该点双连通分量中判断其是否为二分图(二分图不含奇圈)。如果不是二分图,则表示其含有奇圈。打上标记,最后用点数N-没有被打上标记的点数,就是答案。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
using namespace std;
const int maxn =1e3+;
const int maxm = 1e6+;
struct Edge{
int to,next;
}edges[maxm<<];
bool instack[maxn];
int bccno[maxn],head[maxn],dfn[maxn],low[maxn],clk,top,scc;
stack<int> S;
int col[maxn];
int ans;
bool check[maxn];
int tag[maxn];
bool can[maxn]; bool dfs(int u,int c)
{
col[u]=c;
for(int i=head[u]; i!=-; i=edges[i].next){
int v=edges[i].to;
if(!check[v])
continue;
if(col[v]!=-){
if(col[v]==c)
return false;
continue;
}
if(!dfs(v,!c))
return false;
}
return true;
}
void init()
{
clk = top = scc = ;
memset(head,-,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(bccno,,sizeof(bccno));
memset(instack,,sizeof(instack));
memset(can,,sizeof(can));
} void AddEdge(int u,int v)
{
edges[top].to = v;
edges[top].next =head[u];
head[u] = top++;
} void Tarjan(int u,int id)
{
int v;
low[u]=dfn[u]=++clk;
S.push(u);
instack[u]=true;
for(int i=head[u];~i;i=edges[i].next){
v = edges[i].to;
if(i==(id^)) continue;
if(!dfn[v]){
Tarjan(v,i);
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v]){ //找到一个双连通分量
scc++; //从1开始
int cnt=;
memset(check,,sizeof(check)); //判断是否在同一个双连通分量内
while(true){
int x =S.top();S.pop();
tag[cnt++] = x;
bccno[x]=scc; //确定分量编号
instack[x]=false;
check[x] =true;
if(x==v) break; //找到了自己就要停止标号
}
check[u] = true;
memset(col,-,sizeof(col)); //判断双连通分量内是否有奇圈
if(!dfs(u,)){
can[u] = true;
while(cnt--) can[tag[cnt]] = true;
}
}
}
else if(instack[v])
low[u]= min(low[u],dfn[v]);
} } int G[maxn][maxn]; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T,N,M,u,v,tmp;
while(scanf("%d%d",&N,&M)==){
if(!N) break;
init();
memset(G,,sizeof(G));
for(int i=;i<=M;++i){
scanf("%d%d",&u,&v);
G[u][v] = G[v][u] = ;
}
for(int i=;i<=N;++i){
for(int j=i+;j<=N;++j){
if(!G[i][j]){
AddEdge(i,j);
AddEdge(j,i);
}
}
}
for(int i=;i<=N;++i){
if(!dfn[i])
Tarjan(i,-);
}
ans= N;
for(int i=;i<=N;++i){
if(can[i]) ans--;
}
printf("%d\n",ans);
}
return ;
}

POJ - 2942 Knights of the Round Table (点双联通分量+二分图判定)的更多相关文章

  1. 【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)

    [POJ 2942]Knights of the Round Table(双联通分量+染色判奇环) Time Limit: 7000MS   Memory Limit: 65536K Total Su ...

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

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

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

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

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

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

  5. 【洛谷 SP2878】Knights of the Round Table(双联通分量)

    先放这吧,没时间写,明天再补 "明天到了" 题目链接 题意:求不在任何奇环内的点的数量. Tarjan求点双联通分量,然后再染色判断是不是二分图就好了. 只是不懂为什么Tarjan ...

  6. POJ 2942 Knights of the Round Table 黑白着色+点双连通分量

    题目来源:POJ 2942 Knights of the Round Table 题意:统计多个个骑士不能參加随意一场会议 每场会议必须至少三个人 排成一个圈 而且相邻的人不能有矛盾 题目给出若干个条 ...

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

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

    http://poj.org/problem?id=2942 各种逗.... 翻译白书上有:看了白书和网上的标程,学习了..orz. 双连通分量就是先找出割点,然后用个栈在找出割点前维护子树,最后如果 ...

  9. POJ 2942 Knights of the Round Table

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

随机推荐

  1. android 开发积累

    1.ListView滚动黑屏问题 ListView滚动时,数据项变成黑色 问题解决办法:通过添加 android:cacheColorHint = "#00000000" 将背景设 ...

  2. Tweened Animations 渐变动作

    Tweened Animations 渐变动作 Animations分两类: 第一类:渐变的(Tweened): 淡入淡出(Alpha),旋转(Rotate),移动(Translate),缩放(Sca ...

  3. C++ Base64编码解码、MD5及TEA加密解密

    Crypto.h以及Crypto.cpp Crypto.h  123456789101112131415161718192021222324252627282930313233343536373839 ...

  4. <转>RestKit在iOS项目中的使用,包含xcode配置说明

    本文转载至 http://www.cnblogs.com/visen-0/archive/2012/05/03/2480693.html 最近在iPhone工程中添加RestKit并编译,但是由于之前 ...

  5. Django - admin后台、auth权限

    admin后台 一.创建一个管理员用户 (1).设置时区.语言(可选步骤) 打开settings.py,改成下面那样 LANGUAGE_CODE = 'zh-Hans' TIME_ZONE = 'As ...

  6. noip2006 金明的预算

    题目链接:传送门 题目大意:略.. 题目思路:其实单就这道题来说,一个主件最多两个附件,且附件不再包含附件,所以很简单,但是如果主件的附件无限制,附件也可包含无限制的附件,应该怎么做? 首先推荐一篇论 ...

  7. 【BZOJ4379】[POI2015]Modernizacja autostrady 树形DP

    [BZOJ4379][POI2015]Modernizacja autostrady Description 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径为最远的两个点的距离,请输 ...

  8. TCP原理

    1.http://coolshell.cn/articles/11564.html 2.http://coolshell.cn/articles/11609.html 3.一站式学习wireshark ...

  9. threading模块、ThreadLocal

    一.threading模块 1.线程对象的创建 1.1 Thread类直接创建 import threading import time def countNum(n): # 定义某个线程要运行的函数 ...

  10. x265探索与研究(六):main()函数

    x265探索与研究(六):main()函数 x265源代码的入口函数是main(),本文分析main()的主要功能. 首先给出main()函数的功能及其代码结构:其次给出main()函数源代码以及分析 ...