题意

有n个骑士经常举行圆桌会议,商讨大事。每次圆桌会议至少应有3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置。如果发生意见分歧,则需要举手表决,因此参加会议的骑士数目必须是奇数,以防赞同和反对票一样多。知道哪些骑士相互憎恨之后,你的任务是统计有多少个骑士不可能参加任何一个会议。

分析

建模:以骑士为结点建立无向图G。如果两个骑士可以相邻,那么就在他们之间连一条无向边,则题目转化为,求并不在任何一个奇圈上的点的个数。如果图G不连通,应对每个连通分量分别求解。

我们首先要找出图中所有的双连通分量(因为简单圈上所有的结点必属于一个双连通分量),然后判断每个连通分量是否含有奇圈。我们知道二分图不存在奇圈,所以我们对每个双连通分量进行二分染色进行判断就可以。

这里还有一个很重要的结论:如果结点v所属的某个双连通分量B不是二分图,那么v一定属于一个奇圈。训练指南上有这个证明

主算法:对于每个连通分量的双连通分量B,若他不是二分图,给B中的所有结点标记为“在奇圈上”。注意,由于每个割顶属于多个双连通分量,他可能会被标记多次,需要特殊处理一下。

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector> using namespace std;
const int maxn=+;
const int maxm=+;
int vis[maxn][maxn];
int n,m,sz;
int head[maxn],to[maxm],Next[maxm];
struct Edge{
int u,v;
};
void add_edge(int a,int b){
++sz;
to[sz]=b;Next[sz]=head[a];head[a]=sz;
}
int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;
vector<int>bcc[maxn];
stack<Edge>S;
int dfs(int u,int fa){
int lowu=pre[u]=++dfs_clock;
int child=;
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
Edge e=(Edge){u,v};
if(!pre[v]){
S.push(e);
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u]){
iscut[u]=;
bcc_cnt++;bcc[bcc_cnt].clear();
for(;;){
Edge x=S.top();S.pop();
if(bccno[x.u]!=bcc_cnt){
bcc[bcc_cnt].push_back(x.u);
bccno[x.u]=bcc_cnt;
}
if(bccno[x.v]!=bcc_cnt){
bcc[bcc_cnt].push_back(x.v);
bccno[x.v]=bcc_cnt;
}
if(x.u==u&&x.v==v)break;
}
}
}
else if(pre[v]<pre[u]&&v!=fa){
S.push(e);
lowu=min(lowu,pre[v]);
}
}
if(fa<&&child==)iscut[u]=;
return lowu;
}
void find_bcc(int n){
memset(pre,,sizeof(pre));
memset(iscut,,sizeof(iscut));
memset(bccno,,sizeof(bccno));
dfs_clock=bcc_cnt=;
for(int i=;i<=n;i++)
if(!pre[i])dfs(i,-);
}
int color[maxn];
bool bipartite(int u,int num){
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
if(bccno[v]!=num)continue;
if(color[v]==color[u])return false;
if(!color[v]){
color[v]=-color[u];
if(!bipartite(v,num))return false;
}
}
return true;
}
int ANS[maxn]; int main(){
//freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
memset(vis,,sizeof(vis));
int a,b;
for(int i=;i<=m;i++){
scanf("%d%d",&a,&b);
vis[a][b]=vis[b][a]=;
}
sz=-;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i==j)continue;
if(!vis[i][j]){
add_edge(i,j);
vis[i][j]=;
}
if(!vis[j][i]){
add_edge(j,i);
vis[j][i]=;
}
}
}
/*for(int i=1;i<=n;i++){
printf("%d :",i);
for(int j=head[i];j!=-1;j=Next[j]){
int v=to[j];
printf("%d ",v);
}
printf("\n");
}*/ find_bcc(n);
/* for(int i=1;i<=n;i++){
printf("%d %d\n",i,bccno[i]);
}
cout<<bcc_cnt<<endl;*/ memset(ANS,,sizeof(ANS));
for(int i=;i<=bcc_cnt;i++){
for(int j=;j<bcc[i].size();j++){
if(iscut[bcc[i][j]]){
bccno[bcc[i][j]]=i;
}
}
memset(color,,sizeof(color));
color[bcc[i][]]=;
if(!bipartite(bcc[i][],i)){
for(int j=;j<bcc[i].size();j++){
int u=bcc[i][j];
ANS[u]=;
}
}
}
int ans=;
for(int i=;i<=n;i++)
if(ANS[i])
ans++;
ans=n-ans;
printf("%d\n",ans);
}
return ;
}

【LA3523 训练指南】圆桌骑士 【双连通分量】的更多相关文章

  1. la3523 白书例题 圆桌骑士 双联通分量+二分图

    具体题解看大白书P316 #include <iostream> #include <algorithm> #include <vector> #include & ...

  2. [LA3523/uva10195]圆桌骑士 tarjan点双连通分量+奇环定理+二分图判定

    1.一个环上的各点必定在同一个点双连通分量内: 2.如果一个点双连通分量是二分图,就不可能有奇环: 最基本的二分图中的一个环: #include<cstdio> #include<c ...

  3. LA 3523 圆桌骑士(二分图染色+点双连通分量)

    https://vjudge.net/problem/UVALive-3523 题意: 有n个骑士经常举行圆桌会议,商讨大事.每次圆桌会议至少应有3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置 ...

  4. 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)

    layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...

  5. 训练指南 UVALive - 5135 (双连通分量)

    layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...

  6. UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)

    由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不在任意一个简单奇圈上的结点个数. 如果不是二分图,一定存在一个奇圈,同一个双连通分量中其它点一定可以加入奇圈.很明显 ...

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

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

  8. 求双连通分量的详解。(根据刘汝佳的训练指南p314)

    无向图的双连通分量 点-双连通图:一个连通的无向图内部没有割点,那么该图是点-双连通图.         注意:孤立点,以及两点一边这两种图都是点-双连通的.因为它们都是内部无割点. 边-双连通图:一 ...

  9. 【LA5135 训练指南】井下矿工 【双连通分量】

    题意 有一座地下稀有金属矿由n条隧道和一些连接点组成,其中每条隧道连接两个连接点.任意两个连接点之间最多只有一条隧道.为了降低矿工的危险,你的任务是在一些连接点处安装太平井和相应的逃生装置,使得不管哪 ...

随机推荐

  1. minio 安装以及使用

    1. 为了方便使用 docker 安装 docker run -p 9000:9000 minio/minio server /export   注意启动显示的 appkey secretkey  C ...

  2. CentOS(五)--Linux系统的分区概念

    一.系统分区 首先先普及一下有关系统分区的一些知识: 硬盘分区有三种,主磁盘分区.扩展磁盘分区.逻辑分区. 一个硬盘主分区至少有1个,最多4个,扩展分区可以没有,最多1个.且主分区+扩展分区总共不能超 ...

  3. jeecg中树形显示的用法

    1.GoodsController中显示的方法如下: @RequestMapping(params = "goodsgrid") @ResponseBody public Obje ...

  4. MySQL查询优化器工作原理解析

    手册上查询优化器概述 查询优化器的任务是发现执行SQL查询的最佳方案.大多数查询优化器,包括MySQL的查询优化器,总或多或少地在所有可能的查询评估方案中搜索最佳方案.对于联接查询,MySQL优化器所 ...

  5. (转)Inno Setup入门(十三)——Pascal脚本(2)

    本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17250933 事件函数(2) function CheckPassw ...

  6. HDU-1937题解

    一.题意 一个N*M的矩形,点表示空地,X表示非空地,给你一个数字k,让你在这N*M的区域内找出一个空地数量不小于k且面积最小的矩形.输出矩形的面积. PS:原题的题意是在难懂啊. 二.思路 1.朴素 ...

  7. Visual Studio Online 删除项目

    TFS Online在经过一段很长时间的预览阶段后,现在已经改名成Visual Studio Online(简称VS Online),正式成为微软的开发测试云在线服务.撸主最近在上面建了几个测试项目玩 ...

  8. Linux 利用hosts.deny 防止暴力破解ssh

    一.ssh暴力破解 利用专业的破解程序,配合密码字典.登陆用户名,尝试登陆服务器,来进行破解密码,此方法,虽慢,但却很有效果. 二.暴力破解演示 2.1.基础环境:2台linux主机(centos 7 ...

  9. zabbix 报警方式之 邮件报警(4)

    一.为什么要自定义邮件脚本报警? 灵活,方便.可以自定义过滤信息. 下面是使用不同方式的邮件报警,一个是利用sendEmail程序来发送报警邮件,第二个是利用python脚本来发送邮件. 二.send ...

  10. react组件生命

    组件的生命周期主要由三个部分组成: Mounting:组件正在被插入DOM中 Updating:如果DOM需要更新,组件正在被重新渲染 Unmounting:组件从DOM中移除 React提供了方法, ...