题目链接

题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件: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中所有节点标记为在 在奇环上,

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <vector>
using namespace std;
const int Max = ;
vector<int> G[Max], bcc[Max];
int odd[Max], color[Max];
int A[Max][Max];
int pre[Max], iscut[Max], bccno[Max];
int dfs_clock, bcc_cnt; struct Edge
{
int u, v;
};
stack<Edge> S;
int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = ;
int Size = (int) G[u].size();
for (int i = ; i < Size; i++)
{
int v = G[u][i];
Edge e;
e.u = u;
e.v = v;
if (!pre[v])
{
S.push(e);
child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if (lowv >= pre[u])
{
iscut[u] = true;
++bcc_cnt;
bcc[bcc_cnt].clear();
for(;;)
{
Edge x = S.top();
S.pop();
if (bccno[x.u] != bcc_cnt)
{
bcc[bcc_cnt].push_back(x.u);
bccno[x.u] = bcc_cnt;
}
if (bccno[x.v] != bcc_cnt)
{
bcc[bcc_cnt].push_back(x.v);
bccno[x.v] = bcc_cnt;
}
if (x.u == u && x.v == v)
break;
}
}
}
else if (pre[v] < pre[u] && v != fa)
{
S.push(e);
lowu = min(lowu, pre[v]);
}
}
if (fa < && child == ) //这里之前不理解,因为在之前判断是割点的时候已经将这种情况当成了割点,但是对于连通分量来说没问题
iscut[u] = false;
return lowu;
}
void find_bcc(int n)
{
memset(pre, , sizeof(pre));
memset(iscut, , sizeof(iscut));
memset(bccno, , sizeof(bccno));
dfs_clock = bcc_cnt = ;
for (int i = ; i < n; i++)
{
if (!pre[i]) //没访问就访问
dfs(i, -);
}
}
bool bipartite(int u, int b) //判断二分图
{
for (int i = ; i < (int) G[u].size(); i++)
{
int v = G[u][i];
if (bccno[v] != b)
continue;
if (color[v] == color[u])
return false;
if (!color[v])
{
color[v] = - color[u]; // 0表示没图,1表示1种颜色,2表示另一种
if (!bipartite(v, b))
return false;
}
}
return true;
}
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) != EOF)
{
if (n == && m == )
break;
for (int i = ; i <= n; i++)
G[i].clear();
memset(A, , sizeof(A));
for (int i = ; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
u--;
v--; // 从0开始
A[u][v] = A[v][u] = ;
}
for (int i = ; i < n; i++)
{
for (int j = i + ; j < n; j++)
{
if (!A[i][j])
{
G[i].push_back(j);
G[j].push_back(i);
}
}
} find_bcc(n); // 找连通分量 // cout << bcc[3][0] << endl;
memset(odd, , sizeof(odd));
for (int i = ; i <= bcc_cnt; i++)
{
memset(color, , sizeof(color));
for (int j = ; j < (int) bcc[i].size(); j++)
bccno[ bcc[i][j] ] = i; //主要处理割顶,一个割点可能属于多个连通分量
int u = bcc[i][];
color[u] = ; if (!bipartite(u, i)) //如果不是二分图就标记
{
for (int j = ; j < (int) bcc[i].size(); j++)
odd[ bcc[i][j] ] = ;
}
}
int ans = n;
for (int i = ; i < n; i++)
if (odd[i]) //没标记的可定一场会议都参加不成
ans--;
printf("%d\n", ans);
}
return ;
}
 

POJ 2942Knights of the Round Table(二分图判定+双连通分量)的更多相关文章

  1. POJ 2942Knights of the Round Table(tarjan求点双+二分图染色)

    Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 13954   Accepted: 4673 Description Bein ...

  2. poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)

    #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #includ ...

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

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

  4. poj 2942--Knights of the Round Table (点的双连通分量)

    做这题简直是一种折磨... 有n个骑士,骑士之间相互憎恨.给出骑士的相互憎恨的关系. 骑士要去开会,围成一圈坐,相互憎恨的骑士不能相邻.开会骑士的个数不能小于三个人.求有多少个骑士不能开会. 注意:会 ...

  5. POJ 2942 Knights of the Round Table (点双连通分量)

    题意:多个骑士要开会,3人及以上才能凑一桌,其中部分人已经互相讨厌,肯定不坐在同一桌的相邻位置,而且一桌只能奇数个人才能开台.给出多个人的互相讨厌图,要求多少人开不成会(注:会议不要求同时进行,一个人 ...

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

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

  7. 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)

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

  8. 【POJ2942】Knights of the Round Table(二分图 点双联通分量)

    题目链接 大意 给定\(N\)个点与\(M\)个关系,每个关系表示某两个点间没有直接的边相连,求不在所有奇环上的点的个数. (\(1\le N\le 1e3,1\le M\le 1e6\)) 思路 考 ...

  9. UVA 1364 - Knights of the Round Table (获得双连接组件 + 二部图推理染色)

    尤其是不要谈了些什么,我想A这个问题! FML啊.....! 题意来自 kuangbin: 亚瑟王要在圆桌上召开骑士会议.为了不引发骑士之间的冲突. 而且可以让会议的议题有令人惬意的结果,每次开会前都 ...

随机推荐

  1. SDRAM和dcfifo的联合

    SDRAM和dcfifo的联合 设计原理 在"SDRAM突发读写页"实验中,留下了一个问题,就是从SDRAM读取数据的速度要与SDRAM的驱动时钟同步,这就造成了读出的数据的速率过 ...

  2. 支持向量机通俗导论(理解SVM的三层境界)

    原文链接:http://blog.csdn.net/v_july_v/article/details/7624837 作者:July.pluskid :致谢:白石.JerryLead 出处:结构之法算 ...

  3. 为什么VC经常输出烫烫烫烫烫烫烫烫

    为什么VC经常输出烫烫烫烫烫烫烫烫 2012-05-07 11:52 by Rollen Holt, 12747 阅读, 4 评论, 收藏, 编辑 在Debug 模式下, VC 会把未初始化的栈内存全 ...

  4. RHEL7挂载ISO做本地yum

    测试环境,网络yum源没有本地yum源下载速度快!Yum比起RPM装包的好处就是可以自己处理依赖关系,也就是自己安装相关的依赖包,用起来也是很方便,但是删包的时候也会删除依赖包,这里要非常小心 01. ...

  5. android Baseadapter 和 ViewHolder的使用

    昨晚学习了徐大神的关于BaseAdapter的讲解,让我受益匪浅特来博客留下印记 说到baseadapter大家一定都不陌生,下面这张图就展示了数据.listview.baseadapter 之间的关 ...

  6. php学习手记

    在学习常量的时候,一直觉得奇怪 为啥常量的时候总是有个“.”在常量的后面,经过学习现在得知该点是 相当于Java当中的“+”用于连接字符 <?php header("Content-t ...

  7. 通过ADO方式连接数据库

    首先你正确安装了MySQL的数据库驱动程序(mysql-connector-odbc-5.1.6-win32.msi )或者64位的 本地连接: 1.在桌面上新建一个空的文本文件mysql.txt,重 ...

  8. 切割haproxy的日志

    日志的切割有以下几种方法: 1.写个定时任务,每天某个时间点把旧的日志重命名,并对服务重启使其重新打开日志并写入. 2.通过管道的方式把新产生的日志写到另外一个日志文件里. 3.通过logrotate ...

  9. 【CodeVS 1198】【NOIP 2012】国王游戏

    http://codevs.cn/problem/1198/ 推导一翻,排好序后,直接上高精度. #include<cstdio> #include<cstring> #inc ...

  10. jquery.ui.widget详解

    案例详解 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...