题目传送门


题目描述

亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求:

  1、相互憎恨的两个骑士不能坐在直接相邻的2个位置。

  2、出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。 如果出现有某些骑士无法出席所有会议(例如这个骑士憎恨所有的其他骑士),则亚瑟王为了世界和平会强制把他剔除出骑士团。

现在给定准备去开会的骑士数n,再给出m对憎恨对(表示某2个骑士之间使互相憎恨的),问亚瑟王至少要剔除多少个骑士才能顺利召开会议?

注意:

  1、所给出的憎恨关系一定是双向的,不存在单向憎恨关系。

  2、由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士。即每个骑士的座位两边都必定各有一个骑士。

  3、一个骑士无法开会,就是说至少有3个骑士才可能开会。


输入格式

输入包含多组测试。 每种情况都以包含两个整数1≤n≤1000且1≤m≤1000000的整数行开始。 数字n是骑士的数量。 接下来的m行描述哪个骑士憎恨哪个骑士。 这m行中的每一行包含两个整数k1和k2,这意味着骑士数k1和骑士数k2彼此讨厌(数字k1和k2在1和n之间)。
输入n=m=0时终止。


输出格式

对于每组测试,输出一个整数,表示必须被驱逐的骑士数量。


样例

样例输入:

5 5
1 4
1 5
2 5
3 4
4 5
0 0

样例输出:

2


题解

些许有些复杂,思维量较大。

注意亚瑟王会召开多次会议,可以参加其中任意一次会议的骑士就可以被保留。

考虑建出原图的补图,其定义为:原来相连的两个点现在不相连,原来不相连的两个点现在相连。

这样的话两个其实可以坐在一起的条件即为他们之间有连边,方便处理。

那么,如果一个骑士可以参加会议,当且仅当他在一个奇环里。

给出两个定理:

  1、如果一个双连通分量内的某些顶点在一个奇圈中(即双连通分量含有奇圈),那么这个双连通分量的其他顶点也在某个奇圈中。

  2、如果一个双连通分量含有奇圈,则他必定不是一个二分图。反过来也成立,这是一个充要条件。

显然利用塔尖求出每一个v-DCC,然后判断这个v-DCC是不是奇环即可。

这时就用到了交叉染色法,dfs时每一条边都和上一条边反色,当发现两条相邻的边同色时即为奇环。

特别注意:此题不能用万能头文件,否则会CE!!!

那些被CE打倒的大佬:

不过结局总会是好的:


代码时刻

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>//不要万能头!!!
using namespace std;
struct rec
{
int nxt;
int to;
}e[1000001];
int head[1001],cnt;
int dfn[1001],low[1001],sta[1001],tot,top;
bool par[1001],vis[1001];
int col[1001];
bool Map[1001][1001];
vector<int> dcc;
void pre_work()//多测不清空,爆零两行泪TAT……
{
cnt=0;
tot=0;
top=0;
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(sta,0,sizeof(sta));
memset(vis,0,sizeof(vis));
memset(Map,0,sizeof(Map));
}
void add(int x,int y)//建边
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
bool dfs(int x,int color)//交叉染色法判奇环
{
col[x]=color;
for(int i=head[x];i;i=e[i].nxt)
{
if(!par[e[i].to])continue;
if(col[e[i].to]==color)return 1;
if(!col[e[i].to]&&dfs(e[i].to,-color))return 1;
}
return 0;
}
void color_solve()//将v-DCC转入数组,方便处理
{
memset(par,0,sizeof(par));
memset(col,0,sizeof(col));
for(int i=0;i<dcc.size();i++)
par[dcc[i]]=1;
if(dfs(dcc[0],1))
for(int i=0;i<dcc.size();i++)vis[dcc[i]]=1;
}
void tarjan(int x)//塔尖
{
dfn[x]=low[x]=++tot;
sta[++top]=x;
for(int i=head[x];i;i=e[i].nxt)
{
if(!dfn[e[i].to])
{
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
if(dfn[x]<=low[e[i].to])//发现v-DCC
{
int y;
dcc.clear();
do
{
y=sta[top--];
dcc.push_back(y);
}while(e[i].to!=y);
dcc.push_back(x);
color_solve();
}
}
else low[x]=min(low[x],dfn[e[i].to]);
}
}
int main()
{
while(1)
{
int n,m;
scanf("%d%d",&n,&m);
if(!n&&!m)break;
pre_work();
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Map[x][y]=Map[y][x]=1;//临接矩阵存图
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(!Map[i][j]){add(i,j);add(j,i);}//链式前项星建反图
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
int ans=0;
for(int i=1;i<=n;i++)//统计可以参加的骑士
if(vis[i])ans++;
printf("%d\n",n-ans);//用总骑士数减去
}
return 0;
}

rp++

[POJ2942]:Knights of the Round Table(塔尖+二分图染色法)的更多相关文章

  1. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

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

  2. 「题解」:[POJ2942]Knights of the Round Table

    问题 E: Knights of the Round Table 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 作为一名骑士是一个非常有吸引力的职业:寻找圣杯,拯救遇难的少女,与 ...

  3. POJ2942 Knights of the Round Table【Tarjan点双联通分量】【二分图染色】【补图】

    LINK 题目大意 有一群人,其中有一些人之间有矛盾,现在要求选出一些人形成一个环,这个环要满足如下条件: 1.人数大于1 2.总人数是奇数 3.有矛盾的人不能相邻 问有多少人不能和任何人形成任何的环 ...

  4. [POJ2942]Knights of the Round Table(点双+二分图判定——染色法)

    建补图,是两个不仇恨的骑士连边,如果有环,则可以凑成一桌和谐的打麻将 不能直接缩点,因为直接缩点求的是连通分量,点双缩点只是把环缩起来 普通缩点                             ...

  5. poj2942 Knights of the Round Table[点双+二分图染色]

    首先转化条件,把无仇恨的人连边,然后转化成了求有哪些点不在任何一个奇环中. 一个奇环肯定是一个点双,所以想到处理出所有点双,但是也可能有的点双是一个偶环,有的可能是偶环和奇环混杂,不好判. 考察奇环性 ...

  6. $POJ2942\ Knights\ of\ the\ Round\ Table$ 图论

    正解:图论 解题报告: 传送门! 一道,综合性比较强的题(我是萌新刚学$OI$我只是想练下$tarjan$,,,$QAQ$ 考虑先建个补图,然后现在就变成只有相互连边的点不能做邻居.所以如果有$K$个 ...

  7. POJ2942 Knights of the Round Table(点双连通分量 + 二分图染色)

    题目大概说要让n个骑士坐成一圈,这一圈的人数要是奇数且大于2,此外有些骑士之间有仇恨不能坐在一起,问有多少个骑士不能入座. 双连通图上任意两点间都有两条不重复点的路径,即一个环.那么,把骑士看做点,相 ...

  8. poj2942 Knights of the Round Table,无向图点双联通,二分图判定

    点击打开链接 无向图点双联通.二分图判定 <span style="font-size:18px;">#include <cstdio> #include ...

  9. POJ2942 Knights of the Round Table 点双连通分量 二分图判定

    题目大意 有N个骑士,给出某些骑士之间的仇恨关系,每次开会时会选一些骑士开,骑士们会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件:1.任意相互憎恨的两个骑士不能相邻.2.开会人数为大于2的奇 ...

随机推荐

  1. Vue.js官方文档学习笔记(一)起步篇

    Vue.js起步 Vue.js介绍 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库 ...

  2. appium+python自动化项目实战(二):项目工程结构

    废话不多说,直接上图: nose.cfg配置文件里,可以指定执行的测试用例.生成测试报告等.以后将详细介绍.

  3. 微信小程序实现滑动删除效果

    在一些app中,随处可见左滑动的效果,在微信小程序中,官方并未提供相关组件,需要我们自己动手写一个类似的效果 下面仅列举出核心代码,具体的优化需要根据你自身的需求 <view class='li ...

  4. Deepin安装 ruby 包管理工具 RVM(适用于 Debian 系列)

    1. 安装 GPG keys 先安装 gpg2 工具 sudo apt install gnupg2 再安装 keys gpg2 --recv-keys 409B6B1796C275462A17031 ...

  5. vscode如何使用?常用插件有哪些?

    vscode下载 官网下载:https://code.visualstudio.com/ 一.汉化中文(官方下载默认为英文,英文好的小伙伴可直接跳过这步) 点击插件按钮搜索 Chinese, 在弹出的 ...

  6. Vue.nextTick 的原理和用途

    转载自https://segmentfault.com/a/1190000012861862 概览 官方文档说明: 用法: 在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法 ...

  7. Java日志打印方法

    一.使用log4j打印日志 1. 下载log4j.jar和commons-logging.jar.     log4j.jar下载地址:http://logging.apache.org/log4j/ ...

  8. svn 介绍及linux下常用操作命令

    1.概念 truck(主干|主线|主分支):是用来做主方向开发的,新功能的开发应放在主线中,当模块开发完成后,需要修改,就用branch. branch(分支):分支开发和主线开发是可以同时进行的,也 ...

  9. (转) 【oracle调优】优化全表扫---cache整张表或索引

    情景分析: 1)某查询必须要走全表扫描 2)该查询执行的频率相当高 3)对执行时间的要求也相当苛刻的话 4)数据库的IO比较吃紧 5)数据库的内存比较宽松 6)该表的大小没有大到离谱 以上情况下,可以 ...

  10. 从位图图像中读取2D纹理(C ++,OpenGL)

    一共有2个.cpp文件和1个.h头文件 步骤: 需要安装GLUT,因为GLUT是第三方库,即它不是OpenGL的一部分.因此,它不是Windows系统API的一部分,因此不属于标准Windows SD ...