POJ - 2942 Knights of the Round Table (点双联通分量+二分图判定)
题意:有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 (点双联通分量+二分图判定)的更多相关文章
- 【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)
[POJ 2942]Knights of the Round Table(双联通分量+染色判奇环) Time Limit: 7000MS Memory Limit: 65536K Total Su ...
- POJ 2942 Knights of the Round Table(双连通分量)
http://poj.org/problem?id=2942 题意 :n个骑士举行圆桌会议,每次会议应至少3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置.如果意见发生分歧,则需要举手表决,因此 ...
- poj 2942 Knights of the Round Table(点双连通分量+二分图判定)
题目链接:http://poj.org/problem?id=2942 题意:n个骑士要举行圆桌会议,但是有些骑士相互仇视,必须满足以下两个条件才能举行: (1)任何两个互相仇视的骑士不能相邻,每个骑 ...
- POJ 2942.Knights of the Round Table (双连通)
简要题解: 意在判断哪些点在一个图的 奇环的双连通分量内. tarjan求出所有的点双连通分量,再用二分图染色判断每个双连通分量是否形成了奇环,记录哪些点出现在内奇环内 输出没有在奇环内的点的数目 ...
- 【洛谷 SP2878】Knights of the Round Table(双联通分量)
先放这吧,没时间写,明天再补 "明天到了" 题目链接 题意:求不在任何奇环内的点的数量. Tarjan求点双联通分量,然后再染色判断是不是二分图就好了. 只是不懂为什么Tarjan ...
- POJ 2942 Knights of the Round Table 黑白着色+点双连通分量
题目来源:POJ 2942 Knights of the Round Table 题意:统计多个个骑士不能參加随意一场会议 每场会议必须至少三个人 排成一个圈 而且相邻的人不能有矛盾 题目给出若干个条 ...
- 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 ...
- 【POJ】2942 Knights of the Round Table(双连通分量)
http://poj.org/problem?id=2942 各种逗.... 翻译白书上有:看了白书和网上的标程,学习了..orz. 双连通分量就是先找出割点,然后用个栈在找出割点前维护子树,最后如果 ...
- POJ 2942 Knights of the Round Table
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 10911 Acce ...
随机推荐
- 运行jsp需要安装_______Web服务器。
运行jsp需要安装_______Web服务器. A.Apache B.tomcat C.WebLogic D.IIS 解答:BC Apache是PHP程序运行的服务器,IIS是.net程序运行的服务器 ...
- 说明Oracle数据库逻辑备份和物理备份的方式。
说明Oracle数据库逻辑备份和物理备份的方式. 解答:Oracle备份包括逻辑备份和物理备份. 1).逻辑备份 数据库的逻辑备份包含读一个数据库记录集和将记录集写入文件. a.输出(Export)输 ...
- java 理解java的三大特性之继承
继承定义了类如何相互关联,共享特性.对于若干个相同或者相识的类,我们可以抽象出他们共有的行为或者属相并将其定义成一个父类或者超类,然后用这些类继承该父类,他们不仅可以拥有父类的属性.方法还可以定义自己 ...
- WebAPI实现移动端上传头像接口
测试时可以直接使用PostMan模拟发送请求 /// <summary> /// 手机端上传头像接口 /// </summary> /// <param name=&qu ...
- js阻止事件冒泡和标签默认行为
////阻止事件冒泡函数和 // 阻止默认浏览器动作(W3C) 要一起使用效果好<a href="/Scripts/newfiber_js_lib/images/1.jpg" ...
- java Thread方法解析: sleep join wait notify notifyAll
转载自: sleep(),yield(),wait()区别详解:http://dylanxu.iteye.com/blog/1322066 join方法详解:http://www.open-open. ...
- docker菜鸟入门
.Docker概念简介 1.1 Docker的应用场景 1.2 Docker的优势 1.3 Docker架构 1.4 Dorcker核心概念 Dockerfile.Docker镜像和Docker容器的 ...
- FBV和CBV的差异
FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV CBV(class base ...
- Java 8 Lambda 表达式详解
一.Java 8 Lambda 表达式了解 参考:Java 8 Lambda 表达式 | 菜鸟教程 1.1 介绍: Lambda 表达式,也可称为闭包,是推动 Java 8 发布的最重要新特性. La ...
- SPOJ Number of Palindromes(回文树)
Number of Palindromes Time Limit: 100MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu ...