http://poj.org/problem?id=2942

题意 :n个骑士举行圆桌会议,每次会议应至少3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置。如果意见发生分歧,则需要举手表决,因此参加会议的骑士数目必须是奇数,以防止赞同和反对的票一样多,知道哪些骑士相互憎恨之后,你的任务是统计有多少个骑士不可能参加任何一个会议。

思路 :这个题牵扯的知识点挺多的,具体的可以参考白书上解释的蛮详细的。

#include <iostream>
#include <stdio.h>
#include <stack>
#include <string.h>
#include <algorithm>
#include <vector> using namespace std;
const int maxn = ; struct Edge
{
int u,v ;
Edge(int u ,int v):u(u),v(v) {}
} ; int pre[maxn],dfs_clock ,iscut[maxn],Bcc_cnt,Bccno[maxn] ;
vector<int>G[maxn],Bcc[maxn] ;
stack<Edge>S ;
int odd[maxn],color[maxn] ;
int A[maxn][maxn] ; int dfs(int u,int fa)
{
int lowu = pre[u] = ++dfs_clock ;
int child = ;
for(int i = ; i < G[u].size() ; i++)
{
int v = G[u][i] ;
Edge e = (Edge)
{
u,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] = ;
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 < 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] ;
if(!bipartite(v,b))
return false ;
}
}
return true ;
} int main()
{
int kase = ,n,m ;
while(scanf("%d %d",&n,&m) == && n)
{
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-- ;
A[u][v] = A[v][u] = ;
}
for(int u = ; u < n ; u++)
{
for(int v = u+ ; v < n ; v++)
if(!A[u][v])
{
G[u].push_back(v);
G[v].push_back(u) ;
}
}
find_Bcc(n) ;
memset(odd,,sizeof(odd)) ;
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++)
odd[Bcc[i][j]] = ;
}
int ans = n ;
for(int i = ; i < n ; i++)
if(odd[i]) ans-- ;
printf("%d\n",ans) ;
}
return ;
}

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

  1. POJ 2942 Knights of the Round Table 黑白着色+点双连通分量

    题目来源:POJ 2942 Knights of the Round Table 题意:统计多个个骑士不能參加随意一场会议 每场会议必须至少三个人 排成一个圈 而且相邻的人不能有矛盾 题目给出若干个条 ...

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

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

  3. poj 2942 Knights of the Round Table - Tarjan

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

  4. POJ 2942 Knights of the Round Table

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

  5. POJ 2942 Knights of the Round Table - from lanshui_Yang

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

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

    题目链接:http://poj.org/problem?id=2942 题意:n个骑士要举行圆桌会议,但是有些骑士相互仇视,必须满足以下两个条件才能举行: (1)任何两个互相仇视的骑士不能相邻,每个骑 ...

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

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

  8. POJ 2942.Knights of the Round Table (双连通)

    简要题解: 意在判断哪些点在一个图的  奇环的双连通分量内. tarjan求出所有的点双连通分量,再用二分图染色判断每个双连通分量是否形成了奇环,记录哪些点出现在内奇环内 输出没有在奇环内的点的数目 ...

  9. POJ - 2942 Knights of the Round Table (点双联通分量+二分图判定)

    题意:有N个人要参加会议,围圈而坐,需要举手表决,所以每次会议都必须是奇数个人参加.有M对人互相讨厌,他们的座位不能相邻.问有多少人任意一场会议都不能出席. 分析:给出的M条关系是讨厌,将每个人视作点 ...

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

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

随机推荐

  1. js如何实现一定时间后去执行一个函数

    js如何实现一定时间后去执行一个函数:在实际需要中可能需要规定在指定的时间之后再去执行一个函数以达成期望的目的,这也就是一个定时器效果,恰好在js中就已经给定了这样的一个函数setTimeout(), ...

  2. SQL SERVER 主键约束

    主键约束: 遵循关系型模型中的第二范式.唯一的识别一条记录,不能为空. CREATE TABLE Persons ( Id_P int NOT NULL PRIMARY KEY, LastName v ...

  3. 对象创建型模式------Abstract Factory(抽象工厂)

    1. 意图    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.2. 别名    Kit3. 动机        假设我们要开发一款游戏,当然为了吸引更多的人玩,游戏难度不能太大 ...

  4. JAVA中REPLACE和REPLACEALL的区别(转)

    replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是:  1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(Char ...

  5. 经历:Java中字符串中按照多个字符拆分或替换:split()和replaceAll()

    一.replaceAll() 今天,遇到了这样的一个字符串[如下代码]: String s="@0|新港@0|天津@0|东莞@0|南沙@0|营口@0|钦州@0|上海@0|汕头@0|连云港@0 ...

  6. eclipse中启动Genymotion模拟器的错误

    错误程序: Output file: C:\Users\wishwzp\.genymotion-eclipse.logLoading Genymotion libraryGenymotion dire ...

  7. union 和 union all 的区别

    Union因为要进行重复值扫描,所以效率低.如果合并没有刻意要删除重复行,那么就使用Union All  两个要联合的SQL语句 字段个数必须一样,而且字段类型要“相容”(一致): 如果我们需要将两个 ...

  8. 第四篇、C_快速、冒泡、选择、插入排序、二分查找排序、归并、堆排序

    1.快速排序 实现: 1.取中间一个数作为支点 2.分别在支点的左右两边进行查找,如果左边查找到比支点大,右边查找到比支点小,就交换位置,如此循环,比支点小的数就排在了左边,比支点大的就排在右边 3. ...

  9. OC3_字典

    // // main.m // OC3_字典 // // Created by zhangxueming on 15/6/12. // Copyright (c) 2015年 zhangxueming ...

  10. [PR & ML 6] [Introduction] Information Theory