题目真心分析不出来。看了白书才明白,不过有点绕脑。

容易想到,把题目给的不相邻的关系,利用矩阵,反过来建图。既然是全部可行的关系,那么就应该能画出含奇数个点的环。求环即是求双连通分量:找出所有的双连通分量,只要分量中的点数是奇数,则排除“must be expelled”的可能性。

判环上的点数用二分图,这个我都想了半天= =,如果是奇数个点,明摆着多出来的一个点放到哪个集合都会与集合内的点连边(这个找三个点自己画画试试就明白了)。0、1染色,本人喜欢用bfs,递归什么的其实都可以。

我自己用缩点做的,果断wa到吐。举个例子:五个点,{1,2,3}{3,4,5},这样3就是一个割顶了,缩点的话是在遍历完邻接表之后,再判断low[u]==dfn[u],如此5个点就缩成了一个点,即一个分量,虽然这个分量包含奇数个点,输出同样是0,但与我们的思路是不一样的。实际情况是分成两个分量,每个分量有三个点,割顶3同时出现在两个分量中。然后想着改进,当把割顶弹出栈后,再弹入,搞啊搞,还是算了,学着白书上用边搞。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<vector>
  4 #include<stack>
  5 #include<algorithm>
  6 using namespace std;
  7
  8 const int MAXN=1111;
  9
 10 struct EDGE{
 11     int u,v;
 12     EDGE(){}
 13     EDGE(int _u,int _v):u(_u),v(_v){}
 14 };
 15
 16 struct Edge{
 17     int v,next;
 18     Edge(){}
 19     Edge(int _v,int _next):v(_v),next(_next){}
 20 }edge[MAXN*MAXN];
 21
 22 int mp[MAXN][MAXN],tol,head[MAXN];
 23 int low[MAXN],dfn[MAXN],bccno[MAXN],iscut[MAXN],TT,bcc_cnt;
 24 int que[MAXN],color[MAXN];
 25 int sign[MAXN];
 26
 27 vector<int >bcc[MAXN];
 28 stack<EDGE >stk;
 29
 30 void init()
 31 {
 32     tol=0;
 33     memset(head,-1,sizeof(head));
 34 }
 35
 36 void add(int u,int v)
 37 {
 38     edge[tol]=Edge(v,head[u]);
 39     head[u]=tol++;
 40 }
 41
 42 void dfs(int u,int fa)
 43 {
 44     low[u]=dfn[u]=++TT;
 45     int son=0;
 46     for(int i=head[u];i!=-1;i=edge[i].next)
 47     {
 48         int v=edge[i].v;
 49         EDGE e=EDGE(u,v);
 50         if(!dfn[v]){
 51             stk.push(e);
 52             son++;
 53             dfs(v,u);
 54             low[u]=min(low[v],low[u]);
 55             if(low[v]>=low[u]){
 56                 iscut[u]=1;
 57                 bcc_cnt++;
 58                 bcc[bcc_cnt].clear();
 59                 while(1)
 60                 {
 61                     EDGE x=stk.top();
 62                     stk.pop();
 63                     if(bccno[x.u]!=bcc_cnt){
 64                         bcc[bcc_cnt].push_back(x.u);
 65                         bccno[x.u]=bcc_cnt;
 66                     }
 67                     if(bccno[x.v]!=bcc_cnt){
 68                         bcc[bcc_cnt].push_back(x.v);
 69                         bccno[x.v]=bcc_cnt;
 70                     }
 71                     if(x.u==u&&x.v==v)
 72                         break;
 73                 }
 74             }
 75         }else if(dfn[v]<dfn[u]&&v!=fa){
 76             stk.push(e);
 77             low[u]=min(low[u],dfn[v]);
 78         }
 79     }
 80     if(fa<0&&son==1)
 81         iscut[u]=0;
 82 }
 83
 84 void find_bcc(int n)
 85 {
 86     memset(low,0,sizeof(low));
 87     memset(dfn,0,sizeof(dfn));
 88     memset(bccno,0,sizeof(bccno));
 89     memset(iscut,0,sizeof(iscut));
 90
 91     TT=bcc_cnt=0;
 92
 93     for(int i=1;i<=n;i++)
 94         if(!dfn[i])
 95             dfs(i,-1);
 96 }
 97
 98 bool bfs(int x,int fa)
 99 {
100     int l,r;
101     l=r=0;
102     que[r++]=x;
103     while(l<r)
104     {
105         int u=que[l++];
106         for(int i=head[u];i!=-1;i=edge[i].next)
107         {
108             int v=edge[i].v;
109             if(bccno[v]!=fa)
110                 continue ;
111             if(color[v]==-1){
112                 color[v]=color[u]^1;
113                 que[r++]=v;
114             }else if(color[v]==color[u])
115                 return false;
116         }
117     }
118     return true;
119 }
120
121 void Bjudge()
122 {
123     memset(sign,0,sizeof(sign));
124     for(int i=1;i<=bcc_cnt;i++)
125     {
126         memset(color,-1,sizeof(color));
127         for(int j=0;j<bcc[i].size();j++)
128             bccno[bcc[i][j]]=i;
129         int u=bcc[i][0];
130         color[u]=0;
131         if(!bfs(u,i)){
132             for(int j=0;j<bcc[i].size();j++)
133                 sign[bcc[i][j]]=1;
134         }
135     }
136 }
137
138 int main()
139 {
140     int n,m;
141     int a,b;
142     while(~scanf("%d%d",&n,&m)!=EOF)
143     {
144         if(!n&&!m)
145             break;
146         memset(mp,0,sizeof(mp));
147         for(int i=0;i<m;i++)
148         {
149             scanf("%d%d",&a,&b);
150             mp[a][b]=mp[b][a]=1;
151         }
152
153         init();
154         for(int i=1;i<=n;i++)
155         {
156             for(int j=i+1;j<=n;j++)
157             {
158                 if(!mp[i][j]){
159                     add(i,j);
160                     add(j,i);
161                 }
162             }
163         }
164
165         find_bcc(n);
166
167         Bjudge();
168
169         int ans=0;
170         for(int i=1;i<=n;i++)
171             if(!sign[i])
172                 ans++;
173         printf("%d\n",ans);
174     }
175     return 0;
176 }
177 /*
178 5 4
179 1 4
180 1 5
181 2 4
182 2 5
183
184 6 8
185 1 4 1 5 1 6
186 2 4 2 5 2 6
187 3 4 3 5
188 */

View Code

最近做了几道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本身是可以与它的祖先连接的!!

转载于:https://www.cnblogs.com/zstu-abc/p/3234037.html

uvalive 3523 Knights of the Round Table 圆桌骑士(强连通+二分图)相关推荐

  1. Uvalive 3523 - Knights of the Round Table (双连通分量+二分图)

    题目链接 https://vjudge.net/problem/UVALive-3523 [题意] 有n个骑士经常举行圆桌会议,每次圆桌会议应至少有3个人参加且人数必须是奇数,相互憎恨的骑士不能坐在圆 ...

  2. POJ2942 UVA1364 Knights of the Round Table 圆桌骑士

    POJ2942 洛谷UVA1364(博主没有翻墙uva实在是太慢了) 以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则 ...

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

    http://poj.org/problem?id=2942 题意: 有N个骑士,给出某些骑士之间的仇恨关系,骑士们开会时会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件: 1:任意相互憎恨的 ...

  4. POJ2942 Knights of the Round Table 点双连通分量 二分图判定

    题目大意 有N个骑士,给出某些骑士之间的仇恨关系,每次开会时会选一些骑士开,骑士们会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件:1.任意相互憎恨的两个骑士不能相邻.2.开会人数为大于2的奇 ...

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

    题意:找出图中不可能在奇圈中的点. [分析]注意到,在不同点双连通分量中的两个点,显然是不会存在圈的.那么这样,问题就划归为在点双连通分量中去找奇圈. [重要性质]在一个点双连通分量中,只要有任意一个 ...

  6. 如果圆桌骑士有特殊情况(Knights of the Round Table)

    题目描述 Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in dis ...

  7. UVA1364 Knights of the Round Table(双连通分量、二分图染色,超详细解释)

    整理的算法模板合集: ACM模板 UVA1364 Knights of the Round Table 题目中要求互相有憎恨关系的人不能坐在相邻的位置,一个圆桌可以很形象地看作是一个环,也就是说我们两 ...

  8. 【POJ - 2942】Knights of the Round Table(点双连通分量,二分图判断奇环奇圈)

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

  9. CRI Round Table圆桌议事-极力推荐提升英语听力口语的必备播客

    CRI Round Table,别名EZFM Round Table或者Round Table圆桌会议,其实都是同一个Round Table,被称之为英文版"锵锵三人行",是观点自 ...

最新文章

  1. Hibernate 所有缓存机制详解
  2. php yield 导出文件,PHP yield 读取大文件
  3. 没有流程的项目管理,都是无用功!
  4. 【NOIP模拟】方格稿纸
  5. 利用dft的定义计算dft的matlab程序_CP2K教程系列之静态计算(Pymatflow篇)
  6. 八皇后解法(回溯法)
  7. 【前端 · 面试 】HTTP 总结(九)—— HTTP 协商缓存
  8. Android LED电子表时钟字体digital font
  9. 电子基础大全:整理了电子设计所需的基础知识
  10. PFC颗粒6.0软件模拟---工程案例
  11. vim打开文件时显示行号
  12. 透视相机怎么得到正交效果
  13. 如何申请微信号测试账号,进行微信开发
  14. 蓝天保卫战之产品测试服务
  15. uniapp+canvas实现app在线电子签名
  16. ggplot2 theme主题参数详解
  17. 数据结构课程设计-推箱子
  18. Go 内存管理与垃圾回收
  19. 网易163企业邮箱注册申请,有什么优惠活动
  20. 程序人生:平民百姓中的这些“二代”究竟有多难

热门文章

  1. google财经板块股票信息查看的猜想
  2. c语言实现动态字符串,C语言怎么实现可变长度字符串
  3. MySQL数据库学习笔记(一)—— 基础概念
  4. 硅谷企业SaaS服务教父:如何衡量与优化SaaS企业的核心指标
  5. c++11 入门基础
  6. Unity3D研究院之两种方式播放游戏视频
  7. 21、TWS API和IB中的新闻和公告
  8. 基于Java+SpringMVC+Mybaties+jsp+layui实现的宿舍管理系统设计与实现
  9. 写给毕业未5年的你和我
  10. mysql导出备份、导入恢复以及迁移(适用虚拟主机)