题目传送门


题目描述

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

  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. zookeeper集群的搭建(CentOS 7)

    注意ip地址为: 虚拟机ip设置 TYPE="Ethernet"BOOTPROTO="static"NAME="enp0s3"DEVICE= ...

  2. [题解][洛谷]_U75702/P5462_X龙珠_论何为字典序

    赛时嫌麻烦,没写 赛后自闭了,写了一下午 题目描述 “X龙珠”是一款益智小游戏.游戏中有 n(2|n)n(2∣n) 个编号互不相同龙珠按照给定的顺序排成一个队列,每个龙珠上面都有一个编号.每次操作时, ...

  3. 洛谷 P2015 二叉苹果树 题解

    题面 裸的树上背包: 设f[u][i]表示在以u为子树的树种选择i条边的最大值,则:f[u][i]=max(f[u][i],f[u][i-j-1]+f[v][k]+u到v的边权); #include ...

  4. Thread 线程 1

    Thread 常用方法: String getName() 返回该线程的名称. void setName(String name) 改变线程名称,使之与参数 name 相同. int getPrior ...

  5. Ubuntu下Win10虚拟机卡顿问题解决

    问题描述 Ubuntu下用VMware创建了一个Windows10的虚拟机,初始给的配置如下: Memory: 4GB Graphics Memory: 1GB Hard Disk: 60GB 用的时 ...

  6. Pycharm Debug 问题

    Pycharm debug 出现如下问题 Connected to pydev debugger (build 181.4668.75) Traceback (most recent call las ...

  7. day 01 常量 注释 int(整型) 用户交互input 流程控制语句if

    python的编程语言分类(重点) if 3 > 2: 编译型: 将代码一次性全部编译成二进制,然后再执行. 优点:执行效率高. 缺点:开发效率低,不能跨平台. 代表语言:C 解释型: 逐行解释 ...

  8. luogu P1852 [国家集训队]跳跳棋

    luogu 直接操作是不可能的,考虑发现一些性质.可以发现如果每次跳的棋子都是两边的,那么最多只有一种方案,那么就把这样操作得到的状态记为当前状态的父亲,从一个状态这样做一定会结束.那么如果两个状态只 ...

  9. WebApi 生成帮助文档及顺便创建简单的测试工具

    http://www.2cto.com/kf/201607/522971.html ==========最终的效果图========== ==========下面开始干活========== 一.创建 ...

  10. 这样讲 SpringBoot 自动配置原理,你应该能明白了吧

    https://juejin.im/post/5ce5effb6fb9a07f0b039a14 前言 小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题 ...