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. 通过反编译看Java String及intern内幕--费元星站长

    通过反编译看Java String及intern内幕   一.字符串问题 字符串在我们平时的编码工作中其实用的非常多,并且用起来也比较简单,所以很少有人对其做特别深入的研究.倒是面试或者笔试的时候,往 ...

  2. Ruby 基础教程 1-1

    1.指定编码方式       第一种 在代码文件首行通过 #encoding:GBK的方式     第二种  ruby -E UTF-8 文件名称     第三种  irb  -E UTF-8   2 ...

  3. poj3984迷宫问题(dfs+stack)

    迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35426   Accepted: 20088 Descriptio ...

  4. pycharm 3.4 亲测可使用到2019年2月的注册码,要用者从速

    注册码: D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1l ...

  5. Unity编辑器 - 资源批处理工具基类

    Unity编辑器 - 资源批处理工具基类 经常要对资源进行批处理,很多时候都是一次性的需求,于是弄个通用脚本. 工具是个弹出面板,处理过程有进度条,如下: 如图,子类只需要重写几个方法: using ...

  6. 游戏AI之群组行为

    群组行为指的是多个对象组队同时进行的情况.每个boid需满足分离,队列,凝聚三个基本的规则. 分离:群组中的每个个体都与相邻的个体保持一定的距离. 队列:群组以相同的速度,向相同的方向移动. 凝聚:与 ...

  7. 51单片机实现定时器00H-FFH、定时器000-255

    #include< reg51.h> #define uint unsigned int #define uchar unsigned char sfr P0M0 = 0x94; sfr ...

  8. 【上传-下载】-jmeter工具

    上 传 ================================================================================================ ...

  9. 日历(Calendar)模块

    #usr/bin/python3 #! -*-conding : utf-8 -*- #2018.3.14 """ 日历(Calendar)模块 此模块的函数都是日历相关 ...

  10. mysql 主从配置笔记

    1.master配置 server-id=1 log-bin=mysql-bin binlog-do-db=testdata binlog-ignore-db=mysql 2.master增加用户 g ...