【LA3523 训练指南】圆桌骑士 【双连通分量】
题意
有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 训练指南】圆桌骑士 【双连通分量】的更多相关文章
- la3523 白书例题 圆桌骑士 双联通分量+二分图
具体题解看大白书P316 #include <iostream> #include <algorithm> #include <vector> #include & ...
- [LA3523/uva10195]圆桌骑士 tarjan点双连通分量+奇环定理+二分图判定
1.一个环上的各点必定在同一个点双连通分量内: 2.如果一个点双连通分量是二分图,就不可能有奇环: 最基本的二分图中的一个环: #include<cstdio> #include<c ...
- LA 3523 圆桌骑士(二分图染色+点双连通分量)
https://vjudge.net/problem/UVALive-3523 题意: 有n个骑士经常举行圆桌会议,商讨大事.每次圆桌会议至少应有3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置 ...
- 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)
layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...
- 训练指南 UVALive - 5135 (双连通分量)
layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...
- UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不在任意一个简单奇圈上的结点个数. 如果不是二分图,一定存在一个奇圈,同一个双连通分量中其它点一定可以加入奇圈.很明显 ...
- poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 9169 Accep ...
- 求双连通分量的详解。(根据刘汝佳的训练指南p314)
无向图的双连通分量 点-双连通图:一个连通的无向图内部没有割点,那么该图是点-双连通图. 注意:孤立点,以及两点一边这两种图都是点-双连通的.因为它们都是内部无割点. 边-双连通图:一 ...
- 【LA5135 训练指南】井下矿工 【双连通分量】
题意 有一座地下稀有金属矿由n条隧道和一些连接点组成,其中每条隧道连接两个连接点.任意两个连接点之间最多只有一条隧道.为了降低矿工的危险,你的任务是在一些连接点处安装太平井和相应的逃生装置,使得不管哪 ...
随机推荐
- PHP----重置阿里云主机的密码
登陆阿里云,找到你的服务器 点击更多,选择重置密码,根据提示就可以了 这个密码用于连接FTP工具和SSH工具
- HDFS(一)
HDFS的概念 HDFS首先是文件系统(FileSystem,FS),尽管这个FS是基于OS原生的文件系统之上:而且这个文件系统是一个抽象概念,HDFS作为一个整体出现,对外(client)隐藏了其内 ...
- sed命令n,N,d,D,p,P,h,H,g,G,x解析
1.sed执行模板=sed '模式{命令1;命令2}'即逐行读入模式空间,执行命令,最后输出打印出来2.为方便下面,先说下p和P,p打印当前模式空间内容,追加到默认输出之后,P打印当前模式空间开端至\ ...
- SPUtils
public class SPUtils { /** * 保存在手机里的SP文件名 */ public static final String FILE_NAME = "my_sp" ...
- appium+python自动化31-android_uiautomator定位
前言 appium就是封装android的uiautomator这个框架来的,所以uiautomator的一些定位方法也可以用 text 1.通过text文本定位语法 new UiSelector() ...
- 20165226 2017-2018-2《Java程序设计》课程总结
目录 一.作业汇总 二.总结 三.问卷调查 一.作业汇总 预备作业1:我期望的师生关系 预备作业2:学习基础和C语言基础调查 预备作业3:linux安装及学习 第一周: Java入门 第一周学习总结 ...
- 一、Jetty介绍
简介: Jetty 是一个用 Java 实现.开源.基于标准的,并且具有丰富功能的 Http 服务器和 Web 容器,可以免费的用于商业行为.Jetty 这个项目成立于 1995 年,现在已经有非常多 ...
- 如何使用 J2EE 连接器架构实现企业应用
JCA (J2EE 连接器架构,javaConnector Architecture)是对J2EE标准集的重要补充.因为它注重的是将Java程序连接到非Java程序和软件包中间件的开发.连接器特指基于 ...
- 1094 The Largest Generation
题意:略. 思路:层序遍历:在结点中增加一个数据域表示结点所在的层次. 代码: #include <cstdio> #include <queue> #include < ...
- Hadoop单机环境搭建整体流程
1. Ubuntu环境安装和基本配置 本例程中在MAC上安装使用的虚拟机Ubuntu系统(64位,desktop): 基本配置 考虑到以后涉及到hadoop的应用便于权限的管理,特别地创建一个ha ...