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

所写的tarjan练习题最难的一道。

说白了难在考得不是纯tarjan。

首先我们把仇恨关系处理成非仇恨关系的图,然后找双连通分量,在双连通分量里的点满足了任意一个人可以和两个(或以上)的人坐一起。

那么我们接下来要判断奇环。

发现性质:如果一个双连通分量有奇环,那么其中任意一点一定在某个奇环上。

也就是说,这些人拼一拼绝对能全部开会成功,我们把他们打上成功标志。

然后搜失败标志的人的个数即可。

判断奇环的方法显然二分图染色。

#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline int read(){
int x=,w=;char ch=;
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*w;
}
const int maxn=;
struct node{
int st;
int to;
int nxt;
}edge[];
int cnt,head[maxn];
void add(int u,int v){
cnt++;
edge[cnt].st=u;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
bool dis[maxn][maxn];
bool ok[maxn];
int color[maxn];
int dfn[maxn];
int low[maxn];
bool inslt[maxn];
int t=;
int n,m;
int numslt[maxn];
stack<int>q;
vector<int>slt[maxn];
int slt_cnt;
void tarjan(int u,int f){
t++;
dfn[u]=t;
low[u]=t;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(!dfn[v]){
q.push(i);
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
slt_cnt++;
slt[slt_cnt].clear();
while(){
int num=q.top();
q.pop();
if(numslt[edge[num].st]!=slt_cnt){
numslt[edge[num].st]=slt_cnt;
slt[slt_cnt].push_back(edge[num].st);
}
if(numslt[edge[num].to]!=slt_cnt){
numslt[edge[num].to]=slt_cnt;
slt[slt_cnt].push_back(edge[num].to);
}
if(edge[num].to==v&&edge[num].st==u)break;
}
}
}else if(f!=v){
if(low[u]>dfn[v]){
q.push(i);
low[u]=dfn[v];
}
}
}
return;
}
bool draw(int u){
bool ret=;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(!inslt[v])continue;
if(color[v]==-){
color[v]=-color[u];
ret|=draw(v);
}else if(color[v]==color[u]){
return ;
}
}
return ret;
}
void clr(){
cnt=;slt_cnt=;
while(!q.empty())q.pop();
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(numslt,,sizeof(numslt));
memset(head,,sizeof(head));
memset(dis,,sizeof(dis));
memset(ok,,sizeof(ok));
return;
}
int main(){
n=read();
m=read();
while(n||m){
clr();
for(int i=;i<=m;i++){
int u=read();
int v=read();
dis[u][v]=dis[v][u]=;
}
for(int i=;i<=n;i++){
for(int j=i+;j<=n;j++){
if(!dis[i][j]){
add(i,j);
add(j,i);
}
}
}
for(int i=;i<=n;i++){
if(!dfn[i]){
tarjan(i,);
}
}
for(int i=;i<=slt_cnt;i++){
memset(inslt,,sizeof(inslt));
memset(color,-,sizeof(color));
int u;
for(int j=;j<slt[i].size();j++){
u=slt[i][j];
inslt[u]=;
}
color[u]=;
if(draw(u)){
for(int j=;j<slt[i].size();j++){
u=slt[i][j];
ok[u]=;
}
}
}
int ans=;
for(int i=;i<=n;i++)if(!ok[i])ans++;
printf("%d\n",ans);
n=read();m=read();
}
return ;
}

POJ2942:Knights of the Round Table——题解的更多相关文章

  1. 「题解」:[POJ2942]Knights of the Round Table

    问题 E: Knights of the Round Table 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 作为一名骑士是一个非常有吸引力的职业:寻找圣杯,拯救遇难的少女,与 ...

  2. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

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

  3. poj2942 Knights of the Round Table 双连通分支 tarjan

    题解:http://blog.csdn.net/lyy289065406/article/details/6756821 讲的很详细我就不多说了. 题目连接:http://poj.org/proble ...

  4. POJ2942 Knights of the Round Table 点双连通分量,逆图,奇圈

    题目链接: poj2942 题意: 有n个人,能够开多场圆桌会议 这n个人中,有m对人有仇视的关系,相互仇视的两人坐在相邻的位置 且每场圆桌会议的人数仅仅能为奇书 问有多少人不能參加 解题思路: 首先 ...

  5. [POJ2942]:Knights of the Round Table(塔尖+二分图染色法)

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

  6. POJ2942:Knights of the Round Table

    传送门 点双练习. 很简单的一道模板题,建立反图,求出点双,二分图判定奇环. //POJ 2942 //by Cydiater //2016.11.2 #include <iostream> ...

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

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

  8. poj2942 Knights of the Round Table,无向图点双联通,二分图判定

    点击打开链接 无向图点双联通.二分图判定 <span style="font-size:18px;">#include <cstdio> #include ...

  9. POJ2942 Knights of the Round Table【Tarjan点双联通分量】【二分图染色】【补图】

    LINK 题目大意 有一群人,其中有一些人之间有矛盾,现在要求选出一些人形成一个环,这个环要满足如下条件: 1.人数大于1 2.总人数是奇数 3.有矛盾的人不能相邻 问有多少人不能和任何人形成任何的环 ...

随机推荐

  1. mysql中的直方图采样逻辑

    int handler::sample_next(uchar *buf) { // Temporary set inited to RND, since we are calling rnd_next ...

  2. 使用.net 更新word目录

    方案一.采用OpenXml(服务器不依赖Office组件) 在word生成的最后加上代码: using (WordprocessingDocument docx = WordprocessingDoc ...

  3. JavaScript基本概念(1)-声明提升

    声明提升: function > var > other var提升的时候,只是声明提升,但是赋值还是会在原来的位置. Javascript Hoisting:In javascript, ...

  4. Unity 编辑器扩展

    自定义检视面板的使用: 先是定义一个脚本文件,我们来修饰它的检视面板: [HelpURL("http://www.baidu.com")] public class Atr : M ...

  5. Java并发基础--ThreadLocal

    一.ThreadLocal定义 ThreadLocal是一个可以提供线程局部变量的类,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路,通过为每个线程提供一个独立的变量副本解决了变量 ...

  6. 【springmvc+mybatis项目实战】杰信商贸-1.项目背景

    1.项目背景杰信项目物流行业的项目,杰信商贸是国际物流行业一家专门从事进出口玻璃器皿贸易的公司.公司总部位于十一个朝代的帝王之都西安,业务遍及欧美.随着公司不断发展壮大,旧的信息系统已无法满足公司的快 ...

  7. 贪心算法——Huffman 压缩编码的实现

    1. 如何理解 "贪心算法" 假设我们有一个可以容纳 100 Kg 物品的背包,可以装各种物品.我们有以下 5 种豆子,每种豆子的总量和总价值都各不相同.怎样装才能让背包里豆子的总 ...

  8. 微信小程序:封装全局的promise异步调用方法

    微信小程序:封装全局的promise异步调用方法 一:封装 function POST(url, params) { let promise = new Promise(function (resol ...

  9. Log Files

    Description Nikolay has decided to become the best programmer in the world! Now he regularly takes p ...

  10. Thunder团队第一周 - Scrum会议2

    Scrum会议2 小组名称:Thunder 项目名称:待定 Scrum Master:李传康 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康(M ...