poj 2942 圆桌武士
来源:互联网 发布:某企业调查用户从网络 编辑:程序博客网 时间:2024/06/10 05:06
搜索双连通分量。深度优先搜索过程中,用一个栈保存所有经过的节点,判断割点,碰到割点就标记当前栈顶的结点并退栈,直到当前结点停止并标记当前割点。标记过的结点处于同一个双连通分量。
交叉染色搜索奇圈。在一个节点大于2的双连通分量中,必定存在一个圈经过该连通分量的所有结点;如果这个圈是奇圈,则该连通分量内的所有的点都满足条件;若这个圈是偶圈,如果包含奇圈,则必定还有一个奇圈经过所有剩下的点。因此一个双连通分量中只要存在一个奇圈,那么该双联通分量内的所有的点都处于一个奇圈中,在题目中,即武士可以坐成一圈。根据这个性质,只需要在一个双联通分量内找奇圈即可判断该双联通分量是否满足条件。交叉染色法就是在dfs的过程中反复交换着用两种不同的颜色对点染色,若某次dfs中当前结点的子节点和当前结点同色,则找到奇圈。
//poj 2942 圆桌武士,边双连通#include<stdio.h>#include<string.h>#include<vector>const int maxn=1005;using namespace std;struct edge{int s,t;int next;int vis;}edge[maxn*maxn*2];int head[maxn];int E=0;void add(int s,int t){edge[E].s=s;edge[E].t=t;edge[E].vis=0;edge[E].next=head[s];head[s]=E++;}bool map[maxn][maxn];int Btype,Time,tot;int dfn[maxn],low[maxn],Belong[maxn],odd[maxn];bool mark[maxn];int st[maxn*maxn],top,col[maxn];int n,m;bool find(int s){int t,i;for(i=head[s];i!=-1;i=edge[i].next){t=edge[i].t;if(mark[t]){if(col[t]==-1){col[t]=!col[s];return find(t);}else if(col[t]==col[s]) return 1;}}return 0;}void color(int s){int i;memset(mark,0,sizeof(mark));do{i=st[top--];mark[edge[i].s]=1;mark[edge[i].t]=1;}while(edge[i].s!=s);memset(col,-1,sizeof(col));col[s]=0;if(find(s)){for(i=1;i<=n;i++){if(mark[i]) odd[i]=1;}}}inline int min(int a,int b){return a<b?a:b;}void dfs(int s){int i,t;dfn[s]=low[s]=++Time;for(i=head[s];i!=-1;i=edge[i].next){if(edge[i].vis) continue;edge[i].vis=edge[i^1].vis=1;t=edge[i].t;st[++top]=i;if(!dfn[t]){dfs(t);low[s]=min(low[s],low[t]);if(low[t]>=dfn[s]) color(s);}else low[s]=min(low[s],dfn[t]);}}inline void SCC(){int i;Time=0;top=0;memset(dfn,0,sizeof(dfn));memset(odd,0,sizeof(odd));for(i=1;i<=n;i++) if(!dfn[i])dfs(i);}inline int solve(){int res=0,i;SCC();for(i=1;i<=n;i++) if(!odd[i]) res++;return res;}void read_data(){int i,j,a,b;for(i=1;i<=n;i++)for(j=1;j<=n;j++)map[i][j]=1;for(i=0;i<m;i++){scanf("%d%d",&a,&b);map[a][b]=map[b][a]=0;}memset(head,-1,sizeof(head));E=0;for(i=1;i<=n;i++)for(j=i+1;j<=n;j++){if(map[i][j]){add(i,j);add(j,i);}}}int main(){while(scanf("%d%d",&n,&m),n||m){read_data();printf("%d\n",solve());}return 0;}
- poj 2942 圆桌武士
- poj 2942 圆桌武士 双连通分量(BCC)+二分图+奇圈判断
- POJ 2942 圆桌骑士问题。
- POJ 2942 圆桌骑士 点双连通+二分图判定
- poj 2942 圆桌骑士 无向图割点 奇圈 交叉染色
- poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)
- poj 2942 圆桌骑士 二分图判定判奇圈,点双连通分量 大白经典题目
- poj 2942-圆桌骑士(点双连通分量+二分图)
- (点双联通分量模板)POJ 2942 Knights of the Round Table 圆桌骑士
- [POJ]2942 圆桌骑士 点双连通分量 + 二分图染色
- 《魔武士》
- 秃头武士
- 武士2
- 圆桌问题
- 圆桌骑士团
- 圆桌问题
- 搬圆桌
- 搬圆桌
- poj 2954 pick定理
- pku 3348 计算几何 求凸包面积
- hdu 3718 KM最优匹配
- hdu 3711 暴力
- poj 2186 popular cows 强连通缩点
- poj 2942 圆桌武士
- poj 2553 缩点,求出度为0 的点连通块中的点
- poj 1236 强连通好题
- poj 3713 图的三连通
- poj 1410 判断线段与长方形是否相交
- poj、 2546 两圆面积交
- poj 1330 最近公共祖先
- hdu 3486 RMQ + 二分
- RMQ 模板 ,返回区间最值 、 最值的下标