/***昨天开了一段时间然后不会。。。今天又看了一上午,虽然不是很彻底,但是最终好事搞定了
真是感觉到心力憔悴。。。。。。。
奇圈:边数为奇数的圈
定理:二分图中不存在奇圈;
***/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int M = 1008;
int low[M],t,dfs[M],instack[M],odd[M],index,bet,cn,stack[M];
int a[M],tmp,number[M],top,color[M],map[M][M];
struct{
int head;
}H[M];
struct{
int u,v,next;
}E[M*M*2];
void add(int u,int v)
{
E[top].v = v;
E[top].next = H[u].head;
H[u].head = top++;
}
void init()
{
memset(map,0,sizeof(map));
memset(E,-1,sizeof(E));
memset(H,-1,sizeof(H));
memset(low,0,sizeof(low));
memset(dfs,0,sizeof(dfs));
memset(instack,0,sizeof(instack));
memset(odd,0,sizeof(odd));
memset(number,0,sizeof(number));
tmp = cn = bet = index = top = 0;
}
bool co_cycle ( int u, int clr ) //判断是否存在奇圈
{
color[u] = clr;
for ( int i = H[u].head; i!=-1; i = E[i].next )
{
int v = E[i].v;
if ( number[v] == bet )
{
if ( color[v] && color[v] == color[u] )
return true;
if ( !color[v] && co_cycle (v, -clr) )
return true;
}
}
return false;
}
void tarjan(int u,int fa)
{
dfs[u] = low[u] = ++index;
stack[++cn] = u;
instack[u] = 1;
for(int i=H[u].head;i!=-1;i=E[i].next)
{
int v = E[i].v;
if(v == fa)continue;
if(!dfs[v])
{
tarjan(v,u);
low[u] = min(low[u],low[v]);
if(low[v]>=dfs[u])
{
bet++;
do
{
t = stack[cn--];
instack[t] = 0;
a[++tmp] = t;
number[t] = bet; // 类似于强联通分量
}while(t!=v);
}
a[++tmp] = u;
memset(color,0,sizeof(color));
if(tmp>=3 && co_cycle(u,1))
{
while(tmp)
odd[a[tmp--]] = 1;
}
else tmp = 0;
}
else
if(instack[v])
low[u] = min(low[u],dfs[v]);
}
}
int main()
{
int n,m;
int u,v;
while(~scanf("%d%d",&n,&m),n+m)
{
init();
while(m --)
{
scanf("%d%d",&u,&v);
map[u][v] = map[v][u] = 1;
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)if(!map[i][j]){
add(i,j);add(j,i);}
for(int i=1;i<=n;i++)
if(!dfs[i]) tarjan(i,-1);
int ans = 0;
for(int i=1;i<=n;i++)
if(!odd[i])ans++;
printf("%d\n",ans);
}
}
poj 2942 奇圈+点双联通分量
最新推荐文章于 2019-08-18 14:33:41 发布