[Cerc2005]Knights of the Round Table
题目描述
有n个骑士经常举行圆桌会议,商讨大事。每次圆桌会议至少有3个骑士参加,且相互憎恨的骑士不能坐在圆桌的相邻位置。如果发生意见分歧,则需要举手表决,因此参加会议的骑士数目必须是大于1的奇数,以防止赞同和反对票一样多。知道那些骑士相互憎恨之后,你的任务是统计有多少骑士不可能参加任何一个会议。
输入格式
包含多组数据,每组数据格式如下: 第一行为两个整数n和m(1<=n<=1000, 1<=m<=10^6)。 以下m行每行包含两个整数k1和k2(1<=k1,k2<=n),表示骑士k1和k2相互憎恨。 输入结束标记为n=m=0
输出格式
对于每组数据,在一行中输出一个整数,即无法参加任何会议的骑士个数。
我们显然需要让没有憎恨关系的骑士来参加会议。所以我们可以先建出原图的补图。
然后我们发现,如果一些骑士要参加会议,那么这些骑士就要构成一个奇环。因为如果是偶环,那么环上的点就不能选完,也就是说必定会有有两个没有连边的点相邻着坐下。而邻座不能是憎恨的人,又由于我们建的是补图,没连边的点就是憎恨的骑士。所以偶环上的骑士不能参加会议。
既然建的是补图,我们随便造个数据画一画可以隐约感觉到,不在同一个点双内的骑士不能参加同一次会议。
其实原因也很简单,因为如果可以参加同一次会议,那么这两个点必须在同一个奇环内。而它们又不在同一个点双内,就不可能在同一个奇环内。
然后这里有一条点双的定理:
如果一个点双内部有奇环,那么整个点双的所有点也必定在某个奇环内。
下面给出证明:我们在点双的奇环上取两个点u,v,那么必定存在奇环外的一个点w,使得u,v,w构成一个简单环。那么u->w的路径和v->w的路径上的点数就可能是奇或偶。不过无论奇或偶,都能跟原来的奇环构成另一个奇环,因为u通过奇环到达v有两条路径,这两条路径要么是奇数个点,要么是偶数个点,所以可以构成另一个奇环。
所以我们的算法出来了:
首先我们可以用Tarjan找出图中所有点双连通分量,然后枚举每个点双连通分量,我们判断它是不是一个奇环。判断奇环的方法就是:
根据二分图的定义,一张二分图是不可以有奇环的。所以我们可以判断这个点双是否是二分图,如果不是那就有奇环。最后答案就是人数减去有奇环的点双的点数和。
时间复杂度为O(N2+M),N2是因为要建补图。其它的时间复杂度都是O(N+M)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 1001
#define maxm 1000001
using namespace std;
vector<int> to[maxn],dcc[maxn];
bool g[maxn][maxn],able[maxn];//able表示能够参加会议
int dfn[maxn],low[maxn],tot;
int stack[maxn],top;
int col[maxn],cnt;
int vis[maxn];
int n,m,ans;
inline int read(){
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
inline void init(){
for(register int i=1;i<=n;i++) for(register int j=1;j<=n;j++) g[i][j]=false;
for(register int i=1;i<=n;i++) dfn[i]=low[i]=vis[i]=col[i]=able[i]=0;
for(register int i=1;i<=n;i++) to[i].clear(),dcc[i].clear();
tot=cnt=0,ans=0;
}
void tarjan(int u){
dfn[u]=low[u]=++tot;
stack[++top]=u;
for(register int i=0;i<to[u].size();i++){
int v=to[u][i];
if(!dfn[v]){
tarjan(v),low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v]){
int w; cnt++;
do{ w=stack[top--],dcc[cnt].push_back(w); }while(w!=v);
dcc[cnt].push_back(u);
}
}else low[u]=min(low[u],dfn[v]);
}
}
bool check(int u,int c,const int &id){
vis[u]=c;
for(register int i=0;i<to[u].size();i++){
int v=to[u][i];
if(col[v]!=id) continue;
if(!vis[v]){
if(check(v,3-c,id)) return true;
}else if(vis[v]==c) return true;
}
return false;
}
int main(){
while(scanf("%d %d",&n,&m)==2&&n&&m){
init();
for(register int i=1;i<=m;i++){
int u=read(),v=read();
g[u][v]=g[v][u]=true;
}
for(register int i=1;i<=n;i++){
for(register int j=1;j<i;j++) if(!g[i][j]){
to[i].push_back(j),to[j].push_back(i);
}
}
for(register int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(register int i=1;i<=cnt;i++){
for(register int j=0;j<dcc[i].size();j++){
col[dcc[i][j]]=i,vis[dcc[i][j]]=0;
}
if(check(dcc[i][0],1,i)){
for(register int j=0;j<dcc[i].size();j++) able[dcc[i][j]]=true;
}
}
for(register int i=1;i<=n;i++) if(!able[i]) ans++;
printf("%d\n",ans);
}
return 0;
}
[Cerc2005]Knights of the Round Table的更多相关文章
- POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 12439 Acce ...
- 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 ...
- 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)
Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress ...
- 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 ...
- UVALive - 3523 - Knights of the Round Table
Problem UVALive - 3523 - Knights of the Round Table Time Limit: 4500 mSec Problem Description Input ...
- 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 黑白着色+点双连通分量
题目来源:POJ 2942 Knights of the Round Table 题意:统计多个个骑士不能參加随意一场会议 每场会议必须至少三个人 排成一个圈 而且相邻的人不能有矛盾 题目给出若干个条 ...
随机推荐
- Spark-5-如何定位导致数据倾斜的代码
数据倾斜只会发生在shuffle过程中.这里给大家罗列一些常用的并且可能会触发shuffle操作的算子:distinct.groupByKey.reduceByKey.aggregateByKey.j ...
- Python 的 10 个开发技巧!太实用了
1. 如何在运行状态查看源代码? 查看函数的源代码,我们通常会使用 IDE 来完成. 比如在 PyCharm 中,你可以 Ctrl + 鼠标点击 进入函数的源代码. 那如果没有 IDE 呢? 当我们想 ...
- Windows7里面怎么实现FTP服务功能
1.安装FTP服务 点击:计算机 -->属性 --> 控制面板主页 --> 程序 --> 打开或关闭Windows功能 2. 调出管理工具 操作: 鼠标点击工具栏,选择属性,选 ...
- maven项目修改名称后,打包名称和现在名称不一致
将pom.xm文件中 <artifactId>health</artifactId> 修改成现在项目名称,然后 maven clean ->maven install 如 ...
- CGLIB(Code Generation Library)详解
什么是CGLIB CGLIB是一个强大的.高性能的代码生成库.其被广泛应用于AOP框架(Spring.dynaop)中,用以提供方法拦截操作.Hibernate作为一个比较受欢迎的ORM框架,同样使用 ...
- 阿里巴巴java开发手册-嵩山版 下载
引言 今天阿里巴巴开发手册嵩山版又发布了,距离上次泰山版发布才仅仅几个月.是不是有的同学又要感叹下这速度也太快了点吧.我泰山版还没看完,嵩山版直接来了.没看完不要紧,我们直接看嵩山版本就好了.一次性把 ...
- junit 测试用例多并发
最近再用测试用例写个多并发,但是测试用例一运行完程序就结束啦.还没有等到多线程运行完.这个时候可以用断点在多线程后面停住或者让主线程睡眠多一些
- C语言全排列
#include <stdio.h> int m=5; char s[]="12345"; void Swap(char *a, char *b)//元素交换 { ch ...
- SQL数据库创建,创建表,增删改查
创建数据库:create datebase数据库名 删除数据库:drop datebase 数据库名称 创建表格式: create table 表名(字段名1,字段类型1,字段名2,字段类型2) 查询 ...
- WebService的开发手段
一.WebService的开发手段 目前有关webService的开发手段有2种 1.JDK开发(jdk必须是1.6及以上版本,因为jdk是在1.6版本中引入并支持webservice开发的); 2. ...