http://poj.org/problem?id=2942

题意:

有N个骑士,给出某些骑士之间的仇恨关系,骑士们开会时会围坐在一个圆桌旁。一次会议能够顺利举行,要满足两个条件:

1:任意相互憎恨的两个骑士不能相邻

2:开会人数为大于2的奇数

若某个骑士任何会议都不能参加,那么就必须将他踢出,给出骑士之间的仇恨关系,问最少需要踢出多少个骑士?


思路:

题目要求踢出的人最少,那么其实应该都能尽量坐下来,又不能与仇恨的骑士相邻。而题目给出的是骑士之间的仇恨关系,因此我们首先建立补图,先将给出的仇恨关系以骑士为顶点建立边,然后撤销这些边,将其余可以连的边都连上便是原图的补图。骑士要能围坐在一个圆桌,就是图中顶点能在一个圈中,即在一个双连通分量里,而题目要求的要开会的人数是大于2的奇数那么此题就是求最多有多少个骑士在奇圈中。

要求最多有多少骑士在奇圈中,关于奇圈我们要承认这两个定理:

1:若双连通分量中有一个奇圈,则该双连通分量中的所有点都在某个奇圈中

2:若一个双连通分量有奇圈,那么该双连通分量必定不是二分图,他们是充分必要条件。判断是否是二分图可以用交叉染色法,即深度优先搜索染色,如果搜到一个节点的子节点已经染色并且与自己相同,说明不是二分图,那么双连通分量中有奇圈。

这里注意双连通分量里的顶点个数是否是奇数与该双连通分量是否是奇圈无关。


我们可以用tarjan求出每个双连通分量,在其顶点大于2的前提下,对每次求出的双连通分量,根据交叉染色法判断是否有奇圈,如果有,那么这个双连通分量中的点都不用删除(标记一下即可)。

最后,没被标记的肯定不是任何一个奇圈中的顶点。


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
const int maxn = 1010;
const int maxm = 1000100;
int map[maxn][maxn];
int n,m;
int dfn[maxn],low[maxn],instack[maxn],dep;
int scc,tmp[maxn],block[maxn];
int color[maxn];//给某个双连通深度优先搜索染色
int expell[maxn];//标记顶点是否在某个奇圈中
int cnt;
stack <int> st;
vector <int> edge[maxn];//补图void init()
{for(int i = 1; i <= n; i++)edge[i].clear();while(!st.empty()) st.pop();memset(map,0,sizeof(map));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(instack,0,sizeof(instack));memset(block,0,sizeof(block));memset(expell,0,sizeof(expell));dep = 0;cnt = 0;scc = 0;
}
//判断奇圈
bool odd_cycle(int u,int col)
{color[u] = col;for(int i = 0; i < (int)edge[u].size(); i++){int v = edge[u][i];if(block[v] == scc){if(color[v] && color[v] == color[u])return true;if(!color[v] && odd_cycle(v,-col))return true;}}return false;
}void tarjan(int u, int fa)
{dfn[u] = low[u] = ++dep;instack[u] = 1;st.push(u);for(int i = 0; i < (int)edge[u].size(); i++){int v = edge[u][i];if(v == fa) continue;if(!dfn[v]){tarjan(v,u);low[u] = min(low[u],low[v]);if(low[v] >= dfn[u]){scc++;int t;do{t = st.top();st.pop();instack[t] = 0;tmp[++cnt] = t;block[t] = scc;}while(t != v);//注意不要让u出栈,因为它可能属于多个双连通分量tmp[++cnt] = u;//u进临时数组memset(color,0,sizeof(color));if(cnt >= 3 && odd_cycle(u,1))//若该双连通分量包含顶点个数大于2并且是奇圈时{while(cnt != 0)expell[ tmp[cnt--] ] = 1;//在奇圈内的点全部标记为1}else cnt = 0;//别忘了将cnt置零}}else if(instack[v])low[u] = min(low[u],dfn[v]);}
}int main()
{int u,v;while(~scanf("%d %d",&n,&m)){if(n == 0 && m == 0) break;init();for(int i = 0; i < m; i++){scanf("%d %d",&u,&v);map[u][v] = map[v][u] = 1;}//求补图for(int i = 1; i <= n-1; i++){for(int j = i+1; j <= n; j++){if(!map[i][j]){edge[i].push_back(j);edge[j].push_back(i);}}}for(int i = 1; i <= n; i++)if(!dfn[i])tarjan(i,-1);int res = 0;for(int i = 1; i <= n; i++)if(expell[i] == 0)res++;printf("%d\n",res);}return 0;
}

poj 2942 Knights of the Round Table(双连通分量+tarjan+二分图判定)相关推荐

  1. POJ - 2942 Knights of the Round Table (双连通分量)

    题目链接 题意 有N个骑士,每个骑士有自己不喜欢的人,你需要选择奇数个骑士开一个圆桌会议,每个骑士不能和自己不喜欢的人挨着坐. 问需要删除那些人,这些人不能组成圆桌会议 思路 按照补图建边求双连通分量 ...

  2. POJ 2942 Knights of the Round Table ★(点双连通分量+二分图判定)

    题意:找出图中不可能在奇圈中的点. [分析]注意到,在不同点双连通分量中的两个点,显然是不会存在圈的.那么这样,问题就划归为在点双连通分量中去找奇圈. [重要性质]在一个点双连通分量中,只要有任意一个 ...

  3. POJ - 2942 Knights of the Round Table(点双缩点+二分图判定)

    题目链接:点击查看 题目大意:国王要在圆桌上召开骑士会议,但是有若干对骑士之间互相憎恨.出于各种各样奇怪的原因,每次开会都必须有以下要求: 相互憎恨的两个骑士不能坐在相邻的两个位置 为了让投票表决议题 ...

  4. POJ 2942 Knights of the Round Table (奇圈+点双联通)

    题意:在亚瑟王的圆桌骑士团中,某些骑士两两之间相互憎恨,这样一来他们开会的时候边不能相邻的坐着.即肯定存在某些人不能参加会议.假如一个骑士所有的会议都不能出席,那么他就会被驱逐.现在已知那些骑士之间相 ...

  5. POJ 2942 Knights of the Round Table 【点双联通 + 二分图染色法判奇环】

    传送门 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1. 相互憎恨的两个骑士不能坐在直接相邻的2个位置: ...

  6. POJ 2942 Knights of the Round Table (算竞进阶习题)

    很巧的一道点双 两个骑士如果相互憎恨,我们考虑连边的话,不太好处理答案,所以我们尝试一下建反图. 如果两个骑士没有相互憎恨,我们就在他们两个人之间连一条无向边,最后要让你会议召开,那么显然是选择任意一 ...

  7. 【POJ - 2942】Knights of the Round Table(点双连通分量,二分图判断奇环奇圈)

    题干: Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in dist ...

  8. UVA1364 Knights of the Round Table(双连通分量、二分图染色,超详细解释)

    整理的算法模板合集: ACM模板 UVA1364 Knights of the Round Table 题目中要求互相有憎恨关系的人不能坐在相邻的位置,一个圆桌可以很形象地看作是一个环,也就是说我们两 ...

  9. POJ2942 UVA1364 Knights of the Round Table 圆桌骑士

    POJ2942 洛谷UVA1364(博主没有翻墙uva实在是太慢了) 以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则 ...

最新文章

  1. 软件测试面试的linux基础知识,linux基础面试题
  2. JNI开发篇——报错:Flag android.useDeprecatedNdk is no longer supported and will be removed in the next……...
  3. js知识点 掘金_关于webpack4的14个知识点,童叟无欺
  4. 【iCore4 双核心板_ARM】例程三十八:DSP MATH库测试
  5. 河南科技大学c语言网络教学平台,计算机基础教学部
  6. 开发html5单页用什么框架,GitHub - mmcai/single-page-react-h5: 基于React框架的单页活动框架,可以基于此代码上进行相关的H5活动等相关内容的开发...
  7. spring boot访问templates目录下的html静态页面
  8. 洛谷 P1762 偶数
  9. Spring与Struts2的整合
  10. 在点光源的基础上利用光域网来分布光的传播范围及方向_daiding
  11. 关于ADS-Matlab联合仿真ADS.RunSimulation()报错的解决方案
  12. 如何用pdfFactory新建打印机并设置属性
  13. Coolie记住用户名和密码
  14. A Death in the Family May Cause Real Heart Break
  15. 简单修改红帽、centos路由及静态路由表
  16. javase printwriter 打印流
  17. springboot 发送邮件 QQ邮箱 535error
  18. 云南省软考报名时间成绩查询云南省教育考试院云南省人事考试网报名入口
  19. PSSH 轻量化运维工具安装和使用
  20. 27岁,人生规划(大方向调整)(持续更新)

热门文章

  1. java定时器整点报时_单片机 整点报时 定时小闹钟程序
  2. java哪几种运算符_java运算符有哪些
  3. 利用无效字节码指令引发逆向工具崩溃(二)
  4. HDOJ 1814 Peaceful Commission
  5. 计算机云的使用方法,云电脑教程:云电脑怎么用?
  6. 明朝后期,翰林学士公鼐执教东宫,时任礼部侍郎
  7. Wrong namespace. Expected ‘com.baizhi.mapper.UserMapper‘ but found ‘com.com.baizhi.mapper.UserMappe
  8. 联表查询求和的一些问题
  9. WordPress主题:Dux主题 V6.4免费分享(113p.cn)
  10. 统计工作随笔—同比与环比(同期为负值)、百分点