poj2942 Knights of the Round Table,点双连通分量,奇环判断
来源:互联网 发布:vs2015编程c语言 编辑:程序博客网 时间:2024/05/09 23:14
联通分量是我以前研究了很久的东西,但是发现还是有很多理解不透彻。
知识还是要反复咀嚼。
这题求的是每个点是否存在于一个奇环中。
首先求点联通分量。
所谓点双连通分量,就是说有两条没有重复点的路径相连的两个点就处在同一个点双连通分量中。
这个算法也可以求出割点(当删掉这个点,将本来联通的一块将变得不连通)的个数。
然后,用交叉染色法判断这个联通分量是否存在奇环。
可以证明的是联通分量中存在奇环,则这个联通分量中所有点都至少在一个奇环中。
用交叉染色法,判断是否存在奇环。就是颜色交替地dfs或bfs。这个证明可以参考
http://my.oschina.net/mustang/blog/85987
这位大牛的文章。
注意本题只有一个点的环是不合法的。不过在交叉染色法中也会过滤掉这种情况。但是如果题目没有这个条件,就需要特判加上这种奇环了。
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define NN 1010#define MM 2010000int first[NN],next[MM],v[MM],dfn[NN],low[NN];int tote,n,m,a,b,mx,totdfn,totb,top,sta[NN],tot;int block[NN][NN];int sat[NN],cnt[NN];int g[NN][NN];int col[NN];inline void addedge(int from,int to){ tote++; next[tote]=first[from]; first[from]=tote; v[tote]=to;}int dfs(int now,int ncol){ int e,vv; col[now]=ncol; for(e=first[now];e!=-1;e=next[e]){ vv=v[e]; if (col[vv]==ncol){ return 1; } else if (col[vv]==2){ if (dfs(vv,ncol^1)) return 1; } } return 0;}int check(int bnum){ int i; if (cnt[bnum]==1) return 0; memset(col,-1,sizeof(col)); for(i=1;i<=cnt[bnum];++i){ col[block[bnum][i]]=2; } return dfs(block[bnum][1],0);}void tarjan(int u,int fa){ //printf("%d %d\n",u,fa); int tmp,vv,e; dfn[u]=low[u]=++totdfn; sta[++top]=u; for(e=first[u];e!=-1;e=next[e]){ vv=v[e]; if (!dfn[vv]){ tarjan(vv,u); if (low[vv]<low[u]) low[u]=low[vv]; if (low[vv]>=dfn[u]) { //这句是与边双连通分量算法的主要差别 totb++; do{ tmp=sta[top--]; block[totb][++cnt[totb]]=tmp; }while(tmp!=vv); block[totb][++cnt[totb]]=u; if (check(totb)){ for(int i=1;i<=cnt[totb];++i){ sat[block[totb][i]]=1; } } } } else if (fa!=vv&&dfn[vv]<low[u]) low[u]=dfn[vv]; }}int bcc(){ memset(dfn,0,sizeof(dfn)); memset(sat,0,sizeof(sat)); memset(cnt,0,sizeof(cnt)); totb=top=totdfn=0; int i; for(i=1;i<=n;i++)if (!dfn[i]){ tarjan(i,-1); } int ans=0; for(i=1;i<=n;++i){ if (sat[i]==0) ans++; } return ans;}int main(){ int i,j,ans; while(scanf("%d%d",&n,&m)&&(n||m)){ memset(first,-1,sizeof(first)); tote=0; memset(g,0,sizeof(g)); for(i=1;i<=m;i++){ scanf("%d%d",&a,&b); g[a][b]=g[b][a]=1; } for(i=1;i<=n;++i) for(j=1;j<=n;++j) if (!g[i][j]&&i!=j) addedge(i,j); ans=bcc(); printf("%d\n",ans); } return 0;}
0 0
- poj2942 Knights of the Round Table,点双连通分量,奇环判断
- 【POJ2942】Knights of the Round Table-点双连通分量+判断奇环
- POJ2942 Knights of the Round Table 点双连通分量,逆图,奇圈
- 【poj2942】圆桌骑士Knights of the Round Table【双连通分量】【二分图】【奇圈】
- POJ 2942 Knights of the Round Table 点的双连通分量 + 奇圈
- poj Knights of the Round Table 点双连通分量
- poj 2942 Knights of the Round Table(补图的求取+双连通分量+奇环的判断)
- Knights of the Round Table-POJ2942(双连通分量+交叉染色)
- ★【双连通分量】【奇环判定】Knights of the Round Table
- LA 3523 Knights of the Round Table(点双连通分量+二分图判断)
- poj2942点双连通奇圈-二分图判断Knights of the Round Table
- poj 2942 Knights of the Round Table 双连通分量
- 【双连通分量】 POJ Knights of the Round Table
- POJ 2942 Knights of The Round Table <双连通分量>
- [双连通分量]LA3523 Knights of the Round Table
- LA3523.Knights of the Round Table圆桌骑士——点双连通分量+二分图判断
- uva 1364 - Knights of the Round Table(点双连通分量,5级)
- poj 2942 Knights of the Round Table (点双连通分量求解)
- C++优化内存分配
- SQL 注入
- Codeforces Valera and Fruits
- 解决n+1问题
- codeforces 455B. A Lot of Games
- poj2942 Knights of the Round Table,点双连通分量,奇环判断
- MyEclipse的配置问题(Ubuntu系统下)
- 初学 stm32 的USB 开发
- Dom编程(动态创建 表格、删除行、删除列)
- 求表中某列第二大的值及外连接的一些语句
- 人第一天富与贵i以后vu
- 表情识别
- HTML5与CSS3权威指南-第23章-案例2代码
- 5.3-比x大的数中最小和比x小的数中最大