zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    23.Vue技术栈开发实战-Icon组件
    shell脚本每行后面多了一个^M的原因和解决办法
    mmap概述
    camera otp介绍
    brk实现
    USB技术浅析
    带你遨游USB世界
    echarts 更换主题颜色
    Hive UDAF介绍与开发
    2020湖北高考理科第一名唐楚玥的学习方法演讲
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2853889.html
Copyright © 2011-2022 走看看