题目链接

题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1。2.总人数为奇数。3.有仇恨的骑士不能挨着坐。问有几个骑士不能和任何人形成任何的圆圈。

分析:以骑士为借点建立无向图G,如果两个骑士可以相邻(即不相互憎恶)建立一条有向边,题目转化成求不在任意一个简单奇圈上(包含奇数个节点的回路)的节点个数,

对于每个双连通分量,看是否存在奇环,若存在那么这个双连通分量中的任意两骑士都可以同时出现在一个奇环里:训练指南P317解释, 双联通分量B中有一个奇环C,奇环C中含有u1和u2两个点,v属于连通分量B,那么v一定存在到达u1和u2的路径,在奇环C中,u1和u2的两条路是一奇一偶的,由于v到u1和u2的两条路径此时必然能够造成一个经过v的奇环

一个奇环就是一场会议

二分图是没有奇环的

主算法:对于每个连通分量的每个双连通分量B,若它不是二分图,给B中所有节点标记为在 在奇环上,

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <stack>
  6 #include <vector>
  7 using namespace std;
  8 const int Max = 1010;
  9 vector<int> G[Max], bcc[Max];
 10 int odd[Max], color[Max];
 11 int A[Max][Max];
 12 int pre[Max], iscut[Max], bccno[Max];
 13 int dfs_clock, bcc_cnt;
 14
 15 struct Edge
 16 {
 17     int u, v;
 18 };
 19 stack<Edge> S;
 20 int dfs(int u, int fa)
 21 {
 22     int lowu = pre[u] = ++dfs_clock;
 23     int child = 0;
 24     int Size = (int) G[u].size();
 25     for (int i = 0; i < Size; i++)
 26     {
 27         int v = G[u][i];
 28         Edge e;
 29         e.u = u;
 30         e.v = v;
 31         if (!pre[v])
 32         {
 33             S.push(e);
 34             child++;
 35             int lowv = dfs(v, u);
 36             lowu = min(lowu, lowv);
 37             if (lowv >= pre[u])
 38             {
 39                 iscut[u] = true;
 40                 ++bcc_cnt;
 41                 bcc[bcc_cnt].clear();
 42                 for(;;)
 43                 {
 44                     Edge x = S.top();
 45                     S.pop();
 46                     if (bccno[x.u] != bcc_cnt)
 47                     {
 48                         bcc[bcc_cnt].push_back(x.u);
 49                         bccno[x.u] = bcc_cnt;
 50                     }
 51                     if (bccno[x.v] != bcc_cnt)
 52                     {
 53                         bcc[bcc_cnt].push_back(x.v);
 54                         bccno[x.v] = bcc_cnt;
 55                     }
 56                     if (x.u == u && x.v == v)
 57                         break;
 58                 }
 59             }
 60         }
 61         else if (pre[v] < pre[u] && v != fa)
 62         {
 63             S.push(e);
 64             lowu = min(lowu, pre[v]);
 65         }
 66     }
 67     if (fa < 0 && child == 1)  //这里之前不理解,因为在之前判断是割点的时候已经将这种情况当成了割点,但是对于连通分量来说没问题
 68         iscut[u] = false;
 69     return lowu;
 70 }
 71 void find_bcc(int n)
 72 {
 73     memset(pre, 0, sizeof(pre));
 74     memset(iscut, 0, sizeof(iscut));
 75     memset(bccno, 0, sizeof(bccno));
 76     dfs_clock = bcc_cnt = 0;
 77     for (int i = 0; i < n; i++)
 78     {
 79         if (!pre[i])   //没访问就访问
 80             dfs(i, -1);
 81     }
 82 }
 83 bool bipartite(int u, int b)  //判断二分图
 84 {
 85     for (int i = 0; i < (int) G[u].size(); i++)
 86     {
 87         int v = G[u][i];
 88         if (bccno[v] != b)
 89             continue;
 90         if (color[v] == color[u])
 91             return false;
 92         if (!color[v])
 93         {
 94             color[v] = 3 - color[u]; // 0表示没图,1表示1种颜色,2表示另一种
 95             if (!bipartite(v, b))
 96                 return false;
 97         }
 98     }
 99     return true;
100 }
101 int main()
102 {
103     int n, m;
104     while (scanf("%d%d", &n, &m) != EOF)
105     {
106         if (n == 0 && m == 0)
107             break;
108         for (int i = 0; i <= n; i++)
109             G[i].clear();
110         memset(A, 0, sizeof(A));
111         for (int i = 0; i < m; i++)
112         {
113             int u, v;
114             scanf("%d%d", &u, &v);
115             u--;
116             v--;  // 从0开始
117             A[u][v] = A[v][u] = 1;
118         }
119         for (int i = 0; i < n; i++)
120         {
121             for (int j = i + 1; j < n; j++)
122             {
123                 if (!A[i][j])
124                 {
125                     G[i].push_back(j);
126                     G[j].push_back(i);
127                 }
128             }
129         }
130
131         find_bcc(n); // 找连通分量
132
133        // cout << bcc[3][0] << endl;
134         memset(odd, 0, sizeof(odd));
135         for (int i = 1; i <= bcc_cnt; i++)
136         {
137             memset(color, 0, sizeof(color));
138             for (int j = 0; j < (int) bcc[i].size(); j++)
139                 bccno[ bcc[i][j] ] = i;  //主要处理割顶,一个割点可能属于多个连通分量
140             int u = bcc[i][0];
141             color[u] = 1;
142
143             if (!bipartite(u, i))  //如果不是二分图就标记
144             {
145                 for (int j = 0; j < (int) bcc[i].size(); j++)
146                     odd[ bcc[i][j] ] = 1;
147             }
148         }
149         int ans = n;
150         for (int i = 0; i < n; i++)
151             if (odd[i])  //没标记的可定一场会议都参加不成
152             ans--;
153         printf("%d\n", ans);
154     }
155     return 0;
156 }

View Code

 

转载于:https://www.cnblogs.com/zhaopAC/p/5344498.html

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

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

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

  2. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  10. uvalive 3523 Knights of the Round Table 圆桌骑士(强连通+二分图)

    题目真心分析不出来.看了白书才明白,不过有点绕脑. 容易想到,把题目给的不相邻的关系,利用矩阵,反过来建图.既然是全部可行的关系,那么就应该能画出含奇数个点的环.求环即是求双连通分量:找出所有的双连通 ...

最新文章

  1. rk3399在linux机上烧写img,烧写固件 — TB-96AI documentation
  2. AlphaGo“兄弟”AlphaFold出世,DeepMind再创记录
  3. Linux下的零拷贝
  4. 本地构建和自动化构建_构建自动化面板
  5. php数组按时间排序,按日期时间在PHP中对数组中的数组进行排序
  6. 机器学习数据包之numpy
  7. c winform 上传文件到mysql_C# winform DevExpress上传图片到数据库【转】
  8. 做骨龄检测_小柚熊:骨龄测试最佳年龄
  9. 侯捷推荐的C++书单
  10. nginx 1.8.0下载
  11. SubSonic 安装与使用
  12. oppo手机怎么投射到电脑屏幕上
  13. 51单片机实训day2——创建Proteus工程以及Proteus基本控件的使用|单片机最小系统电路设计:电源配置 复位电路 晶振电路
  14. 安装anaconda时需要卸载python么_怎么卸载python 安装 anaconda
  15. 继电器——电磁式继电器
  16. 嘻哈说:设计模式之单一职责原则
  17. 数据中台总体技术架构
  18. 2020年世界航天发射统计
  19. 《On Java 8》读书笔记009_多态
  20. MySQL查询分析器EXPLAIN

热门文章

  1. Linux笔记之shell script
  2. 从零开始撸一个Fresco之gif和Webp动画
  3. Java非对称加密开发(三)-代码及说明
  4. SDxCentral 2015年NFV报告
  5. WCF简单教程(2) 聊聊binding
  6. Java多线程问题之同步器CyclicBarrier
  7. 【高效程序员系列】1、好马配好鞍——舒适的工作环境
  8. WPF中实现PropertyGrid的三种方式
  9. vue3的语法使用总结api
  10. git实现ssh免密上传远程gitlab仓库