由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不在任意一个简单奇圈上的结点个数。

如果不是二分图,一定存在一个奇圈,同一个双连通分量中其它点一定可以加入奇圈。很明显,其它点和已知的奇圈相连总是有两条点数一奇一偶的路径,

因此一定可以找到一条回路使得新的这个点加入一个奇圈。

#include<bits/stdc++.h>
using namespace std;
#define bug(x) cout<<#x<<'='<<x<<endl;
const int maxv = +;
const int maxe = maxv*maxv;//开小 int dfn[maxv],low[maxv],bccno[maxv],dfs_clock,bcc_cnt;
bool iscut[maxv];
vector<int> bcc[maxv];
int head[maxv],fro[maxe],to[maxe],nxt[maxe],ecnt; int edges[maxe],top; void addEdge(int u,int v)
{
fro[ecnt] = u;
to[ecnt] = v;
nxt[ecnt] = head[u];
head[u] = ecnt++;
} void tarjan(int u,int fa)
{
dfn[u] = low[u] = ++dfs_clock;
for(int i = head[u]; ~i; i = nxt[i]){
int v = to[i]; if(!dfn[v]){
edges[++top] = i;
tarjan(v,i);
low[u] = min(low[v],low[u]);
if(low[u] >= dfn[u]){
iscut[u] = true;
bcc_cnt++; bcc[bcc_cnt].clear(); //bcc从1开始
int U,V;
do{
int e = edges[top--];
U = fro[e], V = to[e];
if(bccno[U] != bcc_cnt) { bcc[bcc_cnt].push_back(U); bccno[U]=bcc_cnt; }
if(bccno[V] != bcc_cnt) { bcc[bcc_cnt].push_back(V); bccno[V]=bcc_cnt; }
}while(U!=u||V!=v);
}
}else if((i^) != fa && dfn[v] < dfn[u] ){ low[u] = min(low[u],dfn[v]); edges[++top] = i; }// == 比 ^优先级高!第二个条件少了会WA是什么原因
}
} void find_bcc(int n)
{
top = ;
memset(dfn ,,sizeof(dfn));
memset(iscut, ,sizeof(iscut));
memset(bccno, ,sizeof(bccno));
dfs_clock = bcc_cnt = ;
for(int i = ; i < n; i++) {
if(!dfn[i]) {
tarjan(i,-);
iscut[i] = ~nxt[head[i]];// !(nxt[head[i]] == -1);//树根特判,如果只有一个子结点false
}
}
} int color[maxv];
bool bipartite(int u, int b)
{
for(int i = head[u]; ~i; i = nxt[i]){
int v = to[i]; if(bccno[v] != b) continue;
if(color[v] == color[u]) return false;
if(!color[v]){
color[v] = - color[u];
if(!bipartite(v,b)) return false;
}
}
return true;
} bool hate[maxv][maxv];
bool inOdd[maxv]; int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m)){
memset(hate,,sizeof(hate));
while(m--){
int u,v; scanf("%d%d",&u,&v); u--,v--;
hate[u][v] = hate[v][u] = true;
}
memset(head,-,sizeof(head)); ecnt = ;
for(int i = ; i < n; i++)
for(int j = i+; j < n; j++) if(!hate[i][j]){
addEdge(i,j); addEdge(j,i);
}
find_bcc(n);
// bug(bcc_cnt);
memset(inOdd,,sizeof(inOdd));
for(int i = ; i <= bcc_cnt; i++){
memset(color,,sizeof(color));
for(int j = ; j < bcc[i].size(); j++) bccno[bcc[i][j]] = i; //割点,属于多个连通分量,因此特殊处理
int u = bcc[i][];
color[u] = ;
if(!bipartite(u,i)){
for(int j = ; j < bcc[i].size(); j++) inOdd[bcc[i][j]] = true;
}
}
int ans = n;
for(int i= ; i < n; i++) if(inOdd[i]) ans--;
printf("%d\n",ans);
}
return ;
}

UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)的更多相关文章

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

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

  2. UVALive - 3523 - Knights of the Round Table

    Problem  UVALive - 3523 - Knights of the Round Table Time Limit: 4500 mSec Problem Description Input ...

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

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

  4. poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 9169   Accep ...

  5. UVALive 3523 : Knights of the Round Table (二分图+BCC)

    题目链接 题意及题解参见lrj训练指南 #include<bits/stdc++.h> using namespace std; ; int n,m; int dfn[maxn],low[ ...

  6. KNIGHTS - Knights of the Round Table 圆桌骑士 点双 + 二分图判定

    ---题面--- 题解: 考场上只想到了找点双,,,,然后不知道怎么处理奇环的问题. 我们考虑对图取补集,这样两点之间连边就代表它们可以相邻, 那么一个点合法当且仅当有至少一个大小至少为3的奇环经过了 ...

  7. uva 3523 Knights of the Round Table

    题意:给你n,m n为有多少人,m为有多少组关系,每组关系代表两人相互憎恨,问有多少个骑士不能参加任何一个会议. 白书算法指南 对于每个双联通分量,若不是二分图,就把里面的节点标记 #include ...

  8. POJ 2942 Knights of the Round Table 补图+tarjan求点双联通分量+二分图染色+debug

    题面还好,就不描述了 重点说题解: 由于仇恨关系不好处理,所以可以搞补图存不仇恨关系, 如果一个桌子上面的人能坐到一起,显然他们满足能构成一个环 所以跑点双联通分量 求点双联通分量我用的是向栈中pus ...

  9. [LA3523/uva10195]圆桌骑士 tarjan点双连通分量+奇环定理+二分图判定

    1.一个环上的各点必定在同一个点双连通分量内: 2.如果一个点双连通分量是二分图,就不可能有奇环: 最基本的二分图中的一个环: #include<cstdio> #include<c ...

随机推荐

  1. 1.14不使用回车键来读取n个字符

    read是一个重要的bash命令,它用于从键盘或标准输入中读取文本.可以使用read以交互的形式读取来自用户的输入,不过read能做的远不止这些.很多编程语言的输入库都是从键盘读取输入,且只有回车键按 ...

  2. Oracle(1)

    PL/SQL -- 表示注释 ||''|| 拼接字符串 别名 null值和所有数值计算结果都为null 空置值转换函数: nvl(列,所要转换的数) in 相当于用 or 链接. not in 相当于 ...

  3. POJ - 2533 Longest Ordered Subsequence与HDU - 1257 最少拦截系统 DP+贪心(最长上升子序列及最少序列个数)(LIS)

    Longest Ordered Subsequence A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let ...

  4. 使用LinearLayout实现ListView,解决ListView和ScrollView滚动冲突

    在项目中,我们常常会遇到一个ScrollView里面会嵌套ListView的情况,但往往你会发现,ListView和ScrollView的滚动时间会有冲突问题,造成ListView不能完全显示.虽然网 ...

  5. SpringBoot2.0 基础案例(12):基于转账案例,演示事务管理操作

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.事务管理简介 1.事务基本概念 一组业务操作ABCD,要么全部 ...

  6. IDEA导入HttpServlet包

    转载此篇博客,言简意赅.https://blog.csdn.net/liu_yanzhao/article/details/78838670

  7. Mysql 5.7主主复制配置

    MySQL5.7主主复制配置 主机1IP:192.168.1.2主机2IP:192.168.1.4 一.首先安装MySQL 5.71.卸载两台主机系统中已经有的mysql相关软件包rpm -qa | ...

  8. [Android]《Android艺术开发探索》第一章读书笔记

    1. 典型情况下生命周期分析 (1)一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart方法就会被调用. (2)当用户打开新的Activity或者切换到桌面的时候,回调如下 ...

  9. ZROI WC Round1 题解

    ZROI WC Round1 题解 Problem A 题意 一个 \(n \times m\) 格子图,一个人从左上角出发,每次向右或者向下走一格,方法如下: 如果他在最下面一排,那么他会往右行走. ...

  10. Java带token验证的注册登录

    http://blog.csdn.net/huqingpeng321/article/details/52900550 http://blog.csdn.net/l18710006370/articl ...