题意

有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. springboot: 使web项目支持jsp

    1.springboot为什么不推荐使用jsp? 参考地址:https://spring.io/blog/2012/10/30/spring-mvc-from-jsp-and-tiles-to-thy ...

  2. Docker安装ShowDoc

    ShowDoc就是一个非常适合IT团队的在线文档分享工具,它可以加快团队之间沟通的效率. 一.下载showDoc资源 打开 https://github.com/star7th/showdoc 复制其 ...

  3. Python——基础数据类型(补充)

    1.基础数据类型汇总补充 (1)小数据池:   为了节省空间,数字和字符串有,其他的没有[了解]   数字:-5---256之间的数字共用一个内存地址 #(1)i1 = i2 id(i1) == id ...

  4. Unit01: Servlet基础 、 HTTP协议

    Unit01: Servlet基础 . HTTP协议 在页面上输出当前时间 package web; import java.io.IOException; import java.io.PrintW ...

  5. ssi框架学习总结

    框架简介: 相信大家对于mvc的三层架构已经灰常熟悉了,在这就不细讲了,个人感觉ssi的框架结构还是比较典型的mvc三层架构,还是比较容易上手的.关于这块的入门我想特别感谢下FrankHui童鞋,在他 ...

  6. DS04--树

    一.学习总结 1.树结构思维导图 2.树结构学习体会 树这一节遇到最大的困难就是递归不能灵活的运用,总是想用链表那里的知识解决,做了一大堆,程序崩溃也找不到问题出在哪里. 二.PTA实验作业 题目1: ...

  7. 谈谈对zynq的浅显理解

    zynq并不能说是一个嵌入arm核的FPGA.从它的启动过程就可以发现,绝对是arm主导的,所以称它为以高性能FPGA为外设的双核arm或许更为合适.以下是优势: 第一个:开发环境的大集成.从hls到 ...

  8. SpringMVC中注解控制器及数据绑定

    一.Spring2.5之前,我们都是通过实现Controller接口或其他实现来定义我们的处理器类. 二.Spring2.5引入注解式处理器支持,通过@Controller 和 @RequestMap ...

  9. Web App、Hybrid App与Native App的设计差异

    目前主流应用程序大体分为三类:Web App.Hybrid App. Native App. 一.Web App.Hybrid App.Native App 纵向对比 首先,我们来看看什么是 Web ...

  10. django Chinese

    http://usyiyi.cn/translate/django_182/contents.html