uvalive 3523 Knights of the Round Table 圆桌骑士(强连通+二分图)
题目真心分析不出来。看了白书才明白,不过有点绕脑。
容易想到,把题目给的不相邻的关系,利用矩阵,反过来建图。既然是全部可行的关系,那么就应该能画出含奇数个点的环。求环即是求双连通分量:找出所有的双连通分量,只要分量中的点数是奇数,则排除“must be expelled”的可能性。
判环上的点数用二分图,这个我都想了半天= =,如果是奇数个点,明摆着多出来的一个点放到哪个集合都会与集合内的点连边(这个找三个点自己画画试试就明白了)。0、1染色,本人喜欢用bfs,递归什么的其实都可以。
我自己用缩点做的,果断wa到吐。举个例子:五个点,{1,2,3}{3,4,5},这样3就是一个割顶了,缩点的话是在遍历完邻接表之后,再判断low[u]==dfn[u],如此5个点就缩成了一个点,即一个分量,虽然这个分量包含奇数个点,输出同样是0,但与我们的思路是不一样的。实际情况是分成两个分量,每个分量有三个点,割顶3同时出现在两个分量中。然后想着改进,当把割顶弹出栈后,再弹入,搞啊搞,还是算了,学着白书上用边搞。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std; const int MAXN=; struct EDGE{
int u,v;
EDGE(){}
EDGE(int _u,int _v):u(_u),v(_v){}
}; struct Edge{
int v,next;
Edge(){}
Edge(int _v,int _next):v(_v),next(_next){}
}edge[MAXN*MAXN]; int mp[MAXN][MAXN],tol,head[MAXN];
int low[MAXN],dfn[MAXN],bccno[MAXN],iscut[MAXN],TT,bcc_cnt;
int que[MAXN],color[MAXN];
int sign[MAXN]; vector<int >bcc[MAXN];
stack<EDGE >stk; void init()
{
tol=;
memset(head,-,sizeof(head));
} void add(int u,int v)
{
edge[tol]=Edge(v,head[u]);
head[u]=tol++;
} void dfs(int u,int fa)
{
low[u]=dfn[u]=++TT;
int son=;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
EDGE e=EDGE(u,v);
if(!dfn[v]){
stk.push(e);
son++;
dfs(v,u);
low[u]=min(low[v],low[u]);
if(low[v]>=low[u]){
iscut[u]=;
bcc_cnt++;
bcc[bcc_cnt].clear();
while()
{
EDGE x=stk.top();
stk.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(dfn[v]<dfn[u]&&v!=fa){
stk.push(e);
low[u]=min(low[u],dfn[v]);
}
}
if(fa<&&son==)
iscut[u]=;
} void find_bcc(int n)
{
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(bccno,,sizeof(bccno));
memset(iscut,,sizeof(iscut)); TT=bcc_cnt=; for(int i=;i<=n;i++)
if(!dfn[i])
dfs(i,-);
} bool bfs(int x,int fa)
{
int l,r;
l=r=;
que[r++]=x;
while(l<r)
{
int u=que[l++];
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(bccno[v]!=fa)
continue ;
if(color[v]==-){
color[v]=color[u]^;
que[r++]=v;
}else if(color[v]==color[u])
return false;
}
}
return true;
} void Bjudge()
{
memset(sign,,sizeof(sign));
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(!bfs(u,i)){
for(int j=;j<bcc[i].size();j++)
sign[bcc[i][j]]=;
}
}
} int main()
{
int n,m;
int a,b;
while(~scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m)
break;
memset(mp,,sizeof(mp));
for(int i=;i<m;i++)
{
scanf("%d%d",&a,&b);
mp[a][b]=mp[b][a]=;
} init();
for(int i=;i<=n;i++)
{
for(int j=i+;j<=n;j++)
{
if(!mp[i][j]){
add(i,j);
add(j,i);
}
}
} find_bcc(n); Bjudge(); int ans=;
for(int i=;i<=n;i++)
if(!sign[i])
ans++;
printf("%d\n",ans);
}
return ;
}
/*
5 4
1 4
1 5
2 4
2 5 6 8
1 4 1 5 1 6
2 4 2 5 2 6
3 4 3 5
*/
最近做了几道connectivity的题目,总结一下。
关于割顶、桥、双连通、边双连通,以及强连通处理方式有其相似性,关键都与时间戳有关。
其中,割顶->双连通 是low[v]>=dfn[u],桥->边双连通 是low[v]>dfn[u],只是一个等号的差别,其他处理基本相同;而强连通总是伴随着缩点 low[u]==dfn[u](这个一般是做边标记edge[].vis,这样即使是无向图也可以以edge[i^1].vis标记掉,而不影响重边的情况)。事实上,如果不考虑具体的桥,对边-双连通分量的划分就是在做无向图上的缩点操作。
这三个判定条件的位置也有不同。缩点是在遍历完u的邻接表之后,用每个low[v]的值更新low[u],并且u本身不会连到祖先去(这一点很重要),则是一个环,可以缩掉;在无向图中,判断双连通分量,也就是割顶(边-双连通分量&桥 一样),是每遍历一个孩子v,就要判断:low[v]>=dfn[u],只要点u的孩子所能到达的最大值不超过u,那么u就是割顶(删除u后,该子树独立),当然,u的每一个孩子v都可以是被 割顶u 分离,注意u本身是可以与它的祖先连接的!!
uvalive 3523 Knights of the Round Table 圆桌骑士(强连通+二分图)的更多相关文章
- UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不在任意一个简单奇圈上的结点个数. 如果不是二分图,一定存在一个奇圈,同一个双连通分量中其它点一定可以加入奇圈.很明显 ...
- UVALive - 3523 - Knights of the Round Table
Problem UVALive - 3523 - Knights of the Round Table Time Limit: 4500 mSec Problem Description Input ...
- POJ2942 UVA1364 Knights of the Round Table 圆桌骑士
POJ2942 洛谷UVA1364(博主没有翻墙uva实在是太慢了) 以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则 ...
- poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 9169 Accep ...
- UVALive 3523 : Knights of the Round Table (二分图+BCC)
题目链接 题意及题解参见lrj训练指南 #include<bits/stdc++.h> using namespace std; ; int n,m; int dfn[maxn],low[ ...
- KNIGHTS - Knights of the Round Table 圆桌骑士 点双 + 二分图判定
---题面--- 题解: 考场上只想到了找点双,,,,然后不知道怎么处理奇环的问题. 我们考虑对图取补集,这样两点之间连边就代表它们可以相邻, 那么一个点合法当且仅当有至少一个大小至少为3的奇环经过了 ...
- POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 12439 Acce ...
- uva 3523 Knights of the Round Table
题意:给你n,m n为有多少人,m为有多少组关系,每组关系代表两人相互憎恨,问有多少个骑士不能参加任何一个会议. 白书算法指南 对于每个双联通分量,若不是二分图,就把里面的节点标记 #include ...
- UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)
题目大意:有n个骑士要在圆桌上开会,但是相互憎恶的两个骑士不能相邻,现在已知骑士们之间的憎恶关系,问有几个骑士一定不能参加会议.参会骑士至少有3个且有奇数个. 题目分析:在可以相邻的骑士之间连一条无向 ...
随机推荐
- Netty4.x中文教程系列(四) 对象传输
Netty4.x中文教程系列(四) 对象传输 我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持. 首先我们定义一个U ...
- 客户端服务端通信protocol
这个协议不知我在上面耗费了多长时间,也有人问过我咋回事,这个protocol不长,但对于我来说理解起来很费劲,今天回来看看忽然看懂了(80%),只能说不知看了多少遍 其实这些东西应该在来的一个月这样子 ...
- VB程序破解之API断点[bp __vbaVarTstEq]
软件名称:风云足彩1.7软件大小:2.1M下载地址:http://free.ys168.com/?zhinengxuanhao软件保护:注册码编写软件:Microsoft Visual Basic 5 ...
- getHibernateTemplate()为NUll
getHibernateTemplate()为NUll,困扰好几天了,网上也找了好些方法一直解决不掉15 小弟刚刚开始学SSH,是用的Struts2+Hibernate+Spring,运行的时候发现g ...
- jsp bean标签
jsp中存在一个奇奇怪怪的bean标签. 例如 现在在java包中定义一个类test2 package bean; public class test { private int number; pu ...
- hdu 2736 Surprising Strings(类似哈希,字符串处理)
重点在判重的方法,嘻嘻 题目 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> int ...
- POJ 3461 Oulipo(字符串匹配,KMP算法)
题意:给出几组数据,每组有字符串W和T,问你W在T中出现几次. 思路:字符串长度很大,用KMP算法. 一开始写的是:调用KMP算法查找W在T中是否匹配,若匹配,则个数+1.则接下来T的索引移动相应的距 ...
- 李洪强iOS之Foundation框架—字符串
Foundation框架—字符串 一.Foundation框架中一些常用的类 字符串型: NSString:不可变字符串 NSMutableString:可变字符串 集合型: 1) NSArray:O ...
- spring @bean注解
1.@bean注解用于注册一个bean到 到ioc容器中.类似于@component注解 2.@configure注解,相当于指明这个类是配置文件 3.@bean还可以指定initMethod,des ...
- HTML5入门八---缓存控件元素的值
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...