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

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

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

#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. 交互原型设计软件axure rp学习之路(一)

    开始学习之前,请一定要明白:Axure是个极其极其极其简单的软件.因为你所做的就是拖部件,打字,拖部件,打字,最多加个对齐.如果你能把axure当作word或者ppt来用,那你就学会了axure. A ...

  2. Fitnesse框架简单介绍

    1.Fitnesse是什么? 官方的说明:FitNesse is a wiki server. It's also a test execution engine. Fitnesse是一个wiki s ...

  3. js上传文件到后台时序列化数据

    let fd = new FormData() // 定义传递的序列化对象,for (let i = 0; i < addArr.length; i++) { // addArr是选中文件的输入 ...

  4. STL——queue

    1.初始化 需要头文件<queue> queue<int>que; 2.成员函数 C++队列Queue类成员函数如下: back()返回最后一个元素 empty()如果队列空则 ...

  5. 699. Falling Squares

    On an infinite number line (x-axis), we drop given squares in the order they are given. The i-th squ ...

  6. poj3186(区间dp)

    题目链接:http://poj.org/problem?id=3186 题意:给一行n个数,每次可以取出行首或者行末的数,如果第ai是第i次取出的,可以得到ai*i的收益,求最大的总收益: 思路:区间 ...

  7. jzoj6005. 【PKUWC2019模拟2019.1.17】数学 (生成函数+FFT+抽代+高精)

    题面 题解 幸好咱不是在晚上做的否则咱就不用睡觉了--都什么年代了居然还会出高精的题-- 先考虑如果暴力怎么做,令\(G(x)\)为\(F(n,k)\)的生成函数,那么不难发现\[G^R(x)=\pr ...

  8. jmter介绍及安装

    一.   Apache JMeter介绍 1.       Apache JMeter是什么 Apache JMeter 是Apache组织的开放源代码项目,是一个100%纯Java桌面应用,用于压力 ...

  9. 条件分页 分页条件和页参数传递方式一 超链接拼串 方式二 使用查询表单searchForm

    <%-- Created by IntelliJ IDEA. User: jie Date: 2019/5/10 Time: 20:00 To change this template use ...

  10. python进阶05 常用问题库(1)json os os.path模块

    python进阶05 常用问题库(1)json os os.path模块 一.json模块(数据交互) web开发和爬虫开发都离不开数据交互,web开发是做网站后台的,要跟网站前端进行数据交互 1.什 ...