题意:找出图中不可能在奇圈中的点. [分析]注意到,在不同点双连通分量中的两个点,显然是不会存在圈的.那么这样,问题就划归为在点双连通分量中去找奇圈。 [重要性质]在一个点双连通分量中,只要有任意一个奇圈,那么所有的点都可以在一个奇圈内(证明看《算法竞赛入门经典 训练指南》). [重要定理]一个图含奇圈当且仅当图不是二分图. [解题思路]先求出图的点双连通分量(块),然后对每一个块染色判断二分图,统计出不可能在奇圈中的点的个数 [注意]染色判定二分图的算法要写对


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;const int N = 1002;
const int E = 2000002;
struct node{int u, v;int next;
}arc[E];
int cnt, head[N];
void init(){mem(head, -1);cnt = 0;
}
void add(int u, int v){arc[cnt].u = u;arc[cnt].v = v;arc[cnt].next = head[u];head[u] = cnt ++;arc[cnt].u = v;arc[cnt].v = u;arc[cnt].next = head[v];head[v] = cnt ++;
}/* 求点双连通分量 */
int dfn[N], low[N];
set  bcc[N];
int id, bcc_num;
stack  st;
void addbcc(int u, int v){bcc[bcc_num].insert(u);bcc[bcc_num].insert(v);
}
void dfs(int u, int father){dfn[u] = low[u] = ++id;for (int i = head[u]; i != -1; i = arc[i].next){int v = arc[i].v;if (v == father)    continue;if (dfn[v] < dfn[u]){st.push(arc[i]);if (!dfn[v]){dfs(v, u);low[u] = min(low[u], low[v]);if (dfn[u] <= low[v]){++ bcc_num;while(!st.empty()){int a = st.top().u;int b = st.top().v;st.pop();addbcc(a, b);if ((a == u && b == v) || (b == u && a == v) )break;}}}else{low[u] = min(low[u], dfn[v]);}}}
}
void bcc_tarjan(int n){id = bcc_num = 0;mem(dfn, 0);mem(low, 0);while(!st.empty())st.pop();for (int i = 0; i <= n; i ++)bcc[i].clear();for (int i = 1; i <= n; i ++)dfs(i, 0);
}
/* 求点双连通分量 *//* 染色判定二分图 */
int col[N];
bool not_bigragh[N];    //标记某个点双连通分量是不是二分图
void dfs_color(int bcc_id, int u, int color){col[u] = color;for (int i = head[u]; i != -1; i = arc[i].next){if (not_bigragh[bcc_id])return;int v = arc[i].v;if (bcc[bcc_id].find(v) == bcc[bcc_id].end())continue;if (col[v] == col[u]){not_bigragh[bcc_id] = 1;return;}else if (col[v] == -1){dfs_color(bcc_id, v, (color+1)&1);}}
}
bool fill(int bcc_id){      //对某个点双连通分量染色判断二分图set  ::iterator it;for (it = bcc[bcc_id].begin(); it != bcc[bcc_id].end(); it ++){not_bigragh[bcc_id] = 0;int u = *it;mem(col, -1);dfs_color(bcc_id, u, 0);if (not_bigragh[bcc_id])return false;}return true;
}
/* 染色判定二分图 */int res;
bool can[N];        //存某个点能否在一个奇圈中
int solve(int n){res = 0;mem(can, 0);for (int i = 1; i <= bcc_num; i ++){if (!fill(i)){set  ::iterator it;for (it = bcc[i].begin(); it != bcc[i].end(); it ++){can[*it] = 1;}}}for (int i = 1; i <= n; i ++){if (!can[i])res ++;}return res;
}
bool mat[N][N];     //表示i憎恨j的关系矩阵
int main(){int n, m;while(scanf("%d %d", &n, &m) != EOF){if (n == 0 && m == 0)break;init();mem(mat, 0);for (int i = 0; i < m; i ++){int a, b;scanf("%d %d", &a, &b);mat[a][b] = 1;mat[b][a] = 1;}for (int i = 1; i <= n; i ++){for (int j = i+1; j <= n; j ++){if (!mat[i][j]){add(i, j);}}}bcc_tarjan(n);printf("%d\n", solve(n));}return 0;
}

转载于:https://www.cnblogs.com/AbandonZHANG/archive/2013/06/05/4114246.html

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

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

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

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

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

  3. Uvalive 3523 - Knights of the Round Table (双连通分量+二分图)

    题目链接 https://vjudge.net/problem/UVALive-3523 [题意] 有n个骑士经常举行圆桌会议,每次圆桌会议应至少有3个人参加且人数必须是奇数,相互憎恨的骑士不能坐在圆 ...

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

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

  5. poj 2942 Knights of the Round Table(双连通分量+tarjan+二分图判定)

    http://poj.org/problem?id=2942 题意: 有N个骑士,给出某些骑士之间的仇恨关系,骑士们开会时会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件: 1:任意相互憎恨的 ...

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

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

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

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

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

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

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

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

最新文章

  1. 图标尺寸规范_作为刚入门的UI设计师,你需要懂哪些设计规范?
  2. caddy php sock,Caddy环境下一些Web应用程序的配置参考
  3. python中字典的键必须是可以哈希的对象
  4. mysql如何开启远程链接_mysql怎么开启远程连接
  5. C# base和this
  6. 多项“首次”落地 腾讯云数据库助力金融机构国产化
  7. 用深度强化学习玩atari游戏_被追捧为“圣杯”的深度强化学习已走进死胡同
  8. php html class,html中规定元素的类名的属性class
  9. 【黄金分割点】与【斐波那契数列】
  10. bigemap功能介绍
  11. Flex builder3相关
  12. 基于PCA的ORL人脸识别---Python
  13. python学习笔记(2)—— 控制流
  14. 企业级架构的价值体现在哪里?
  15. redhat oracle环境变量配置文件,Redhat7.2(7.1)下oracle8.17的安装手册-数据库专栏,ORACLE...
  16. PostgreSQL 别名
  17. 用HTML+CSS做一个简单好看的校园社团网页
  18. MySQL:让表的时间字段在insert和update时自动更新
  19. GB28181协议简介以及学习GB28181协议所涉及的名词汇总(入门篇)
  20. Google Earth Engine(GEE)——全球12级流域矢量数据免费下载(含数据下载链接)

热门文章

  1. win10蓝牙开关不见了_Win8系统电脑蓝牙图标不见了的解决方法
  2. 计算机分级时无法度量视频播放,Win7 64位系统电脑评分出现“无法度量视频播放性能”怎么解决...
  3. go怎么用改变c语言程序位置,Go与C语言的互操作
  4. excel单元格斜线_Excel技巧 | 如何绘制斜线表头
  5. RabbitMQ和Kafka的区别
  6. linux命令看文件内容,Linux文件内容查看相关命令
  7. linux 线程退出 signal,Linux signal 那些事儿 (3)
  8. lfw2019_来自 LFW SS20 你应该知道的5个时尚趋势
  9. 为什么要嫁就嫁电力男!
  10. 通俗易懂,嵌入式Linux驱动基础