poj2942 点-双联通+二分图染色
Posted walfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj2942 点-双联通+二分图染色相关的知识,希望对你有一定的参考价值。
题意:有一群骑士要坐在一个圆形的桌子上,他们之间有些人相互讨厌,所以不能挨着,要求算出一次也不能坐在桌子上的人,每次会议桌子必须奇数个人,一个人不能开会
题解:可以先建一个补图,要满足题目条件我们只要找出所有奇圈(奇数个点的环),求出点-双联通分量,对于每一个单独的点-双连通分量,如果它一定是一个奇圈,那么不能够通过二分图染色,可以通过画图验证这条结论,那么我们对于所有的奇圈里的点进行染色,最后输出没有染色过的点,因为有可能会出现多次染色的点,所以不能直接每次加点数
坑点:不能用stl,tle了好多发,最后把所有的vector,map都换成了数组就过了,不能用vector存图,那么就用我最喜欢的链式前向星吧= =
#include<map> #include<set> #include<list> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; using namespace __gnu_cxx; const double g=10.0,eps=1e-7; const int N=1000+10,maxn=1000000+10,inf=0x3f3f3f; struct edge{ int to,Next; }e[maxn]; int bcc[N]; int index,num; int cnt,head[N]; int dfn[N],low[N]; int bccno[N]; struct ewedge{int from,to;}; stack<ewedge>s; bool ma[N][N]; int in[N],ok[N]; int color[N]; bool notsub; void add(int x,int y) { e[cnt].to=y; e[cnt].Next=head[x]; head[x]=cnt++; e[cnt].to=x; e[cnt].Next=head[y]; head[y]=cnt++; } void dfs(int u,int f,int p) { if(notsub)return ; color[u]=p; int c=3-p; for(int i=head[u];~i;i=e[i].Next) { int x=e[i].to; if(ok[x]) { if(!color[x])dfs(x,u,c); else { if(color[x]!=c)notsub=1; } } } } void tarjan(int u,int f) { low[u]=dfn[u]=++index; for(int i=head[u];~i;i=e[i].Next) { int x=e[i].to; ewedge e=(ewedge){u,x}; if(x==f)continue; if(!dfn[x]) { s.push(e); tarjan(x,u); low[u]=min(low[u],low[x]); if(low[x]>=dfn[u]) { int res=0; num++; memset(ok,0,sizeof ok); int be=0; for(;;) { ewedge p=s.top();s.pop(); if(bccno[p.from]!=num) { bcc[res++]=p.from; be=p.from; bccno[p.from]=num; ok[p.from]=1; } if(bccno[p.to]!=num) { bcc[res++]=p.to; be=p.to; bccno[p.to]=num; ok[p.to]=1; } if(p.from==e.from&&p.to==e.to)break; } //判断是不是二分图 for(int i=0;i<res;i++) color[bcc[i]]=0; notsub=0; dfs(be,-1,1); if(notsub) { for(int i=0;i<res;i++) in[bcc[i]]=1; } /* cout<<notsub<<"--------"; for(int j=0;j<bcc.size();j++) cout<<bcc[j]<<" "; cout<<endl;*/ } } else { if(dfn[x]<dfn[u])low[u]=min(low[u],dfn[x]); } } } void init(int n) { memset(head,-1,sizeof head); memset(ma,0,sizeof ma); for(int i=1;i<=n;i++) { bccno[i]=dfn[i]=low[i]=in[i]=0; } while(!s.empty())s.pop(); index=num=cnt=0; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { if(!n&&!m)break; init(n); while(m--) { int a,b; scanf("%d%d",&a,&b); ma[a][b]=ma[b][a]=1; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(!ma[i][j]) add(i,j); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1); int ans=0; for(int i=1;i<=n;i++) if(in[i]) ans++; printf("%d\n",n-ans); } return 0; } /************ ************/
以上是关于poj2942 点-双联通+二分图染色的主要内容,如果未能解决你的问题,请参考以下文章
POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]
POJ 2942Knights of the Round Table(双联通分量+染色判奇环)
poj2942 Knights of the Round Table