POJ2942Knights of the Round Table

刘汝佳新书题

题意求是求不在任意一个简单奇圈的点的个数

先求双连通分量,再用二分图判断是否是奇圈

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;
#define MAXN 1005
int A[MAXN][MAXN];
int n,m;

struct Edge{
    int u,v;
};
vector<int>G[MAXN],bcc[MAXN];
int pre[MAXN],iscut[MAXN],bccno[MAXN],dfs_clock,bcc_cnt;
stack<Edge> S;
int dfs(int u,int fa)
{
   int lowu= pre[u]=++dfs_clock;
   int child=0;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        Edge e;
        e.u=u,e.v=v;
        if(!pre[v])
        {
            S.push(e);
            child++;
            int lowv=dfs(v,u);
            lowu=min(lowu,lowv);
            if(lowv>=pre[u])
            {
                iscut[u]=1;
                bcc_cnt++;
                bcc[bcc_cnt].clear();
                for(;;)
                {
                    Edge x=S.top();S.pop();
                    if(bccno[x.u]!=bcc_cnt)
                    {
                        bcc[bcc_cnt].push_back(x.u);
                        bccno[x.u]=bcc_cnt;
                    }
                    if(bccno[x.v]!=bcc_cnt)
                    {
                        bcc[bcc_cnt].push_back(x.v);
                        bccno[x.v]=bcc_cnt;
                    }
                    if(x.u==u&&x.v==v)break;
                }
            }
        }
        else if(pre[v]<pre[u]&&v!=fa)
        {
            S.push(e);
            lowu=min(lowu,pre[v]);
        }
    }
    if(fa<0&&child==1)iscut[u]=0;
    return lowu;
}
//双连通分量
void find_bcc(int n)
{
    memset(pre,0,sizeof(pre));
    memset(iscut,0,sizeof(iscut));
    memset(bccno,0,sizeof(bccno));
    dfs_clock=bcc_cnt=0;
    for(int i=0;i<n;i++)
        if(!pre[i])dfs(i,-1);
}
//判断二分图
int odd[MAXN],color[MAXN];
bool bipartite(int u,int b)
{
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(bccno[v]!=b)continue;
        if(color[v]==color[u])
            return false;
        if(!color[v])
        {
            color[v]=3-color[u];
            if(!bipartite(v,b))return false;
        }
    }
    return true;
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        if(n==0&&m==0)
            break;
        for(int i=0;i<n;i++)
            G[i].clear();
        int a,b;
        memset(A,0,sizeof(A));
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            a--,b--;
            A[b][a]=A[a][b]=1;
        }
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
            {
                if(A[i][j])
                    continue;
                G[i].push_back(j),G[j].push_back(i);
            }
        find_bcc(n);

       memset(odd,0,sizeof(odd)) ;
        for(int i=1;i<=bcc_cnt;i++)
        {
        memset(color,0,sizeof(color));
        for(int j=0;j<bcc[i].size();j++)
            bccno[bcc[i][j]]=i;
        int u=bcc[i][0];
        color[u]=1;
        if(!bipartite(u,i))
            for(int j=0;j<bcc[i].size();j++)
                odd[bcc[i][j]]=1;
        }
        int ans=n;
        for(int i=0;i<n;i++)
            if(odd[i])ans--;

        printf("%d\n",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/2853889.html