• UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)


    题目大意:有n个骑士要在圆桌上开会,但是相互憎恶的两个骑士不能相邻,现在已知骑士们之间的憎恶关系,问有几个骑士一定不能参加会议。参会骑士至少有3个且有奇数个。

    题目分析:在可以相邻的骑士之间连一条无向边,构成一张图G。则问题变成了有几个节点不在奇圈(有奇数个节点的圈)内,并且一个点在圈内最多出现一次。如果G不连通,应该对每一个分量分别求解。奇圈上的点一定在同一个双连通分量内,要找出所有的双连通分量。但是能构成二分图的双连通分量中一定没有奇圈,不能构成二分图的双连通分量中一定含有奇圈,并且分量中所有的点都在奇圈上,所有还要判断每一个双连通分量能不能构成二分图。

    其实就是一道模板题。。。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<vector>
    # include<stack>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    const int maxn=1005;
    struct Edge
    {
        int u,v;
        Edge(int _u,int _v):u(_u),v(_v){}
    };
    stack<Edge>S;
    vector<int>G[maxn],bcc[maxn];
    int bcc_cnt,dfs_cnt,low[maxn],pre[maxn],odd[maxn],color[maxn],bccno[maxn],iscut[maxn],A[maxn][maxn];
    
    int dfs(int u,int fa)
    {
        int lowu=pre[u]=++dfs_cnt;
        int child=0;
        for(int i=0;i<G[u].size();++i){
            int v=G[u][i];
            if(!pre[v]){
                S.push(Edge(u,v));
                ++child;
                int lowv=dfs(v,u);
                lowu=min(lowu,lowv);
                if(lowv>=pre[u]){///存在一个满足条件的v,便能说明u是割点。
                    iscut[u]=1;
                    bcc[++bcc_cnt].clear();
                    while(1)
                    {
                        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(Edge(u,v));
                lowu=min(lowu,pre[v]);
            }
        }
        if(fa<0&&child==1)///根节点只有1个子节点时不是割点。
            iscut[u]=0;
        low[u]=lowu;
        return lowu;
    }
    
    void find_bcc(int n)
    {
        memset(pre,0,sizeof(pre));
        memset(iscut,0,sizeof(iscut));
        memset(bccno,0,sizeof(bccno));
        dfs_cnt=bcc_cnt=0;
        for(int i=0;i<n;++i)
            if(!pre[i])
                dfs(i,-1);
    }
    
    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()
    {
        int n,m,a,b;
        while(scanf("%d%d",&n,&m)&&(n+m))
        {
            memset(A,0,sizeof(A));
            for(int i=0;i<n;++i)  G[i].clear();
            while(m--){
                scanf("%d%d",&a,&b);
                --a,--b;
                A[a][b]=A[b][a]=1;
            }
            for(int i=0;i<n;++i)
                for(int j=i+1;j<n;++j)
                    if(!A[i][j])
                        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
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    AtCoder Regular Contest 066 F Contest with Drinks Hard
    AtCoder Grand Contest 002 D
    AtCoder Regular Contest 076 F
    AtCoder Grand Contest 004 C
    AtCoder Regular Contest 067 F
    转载:Unity3D游戏对象消失enabled、Destroy与active的区别
    Unity3d-AngryBots实例解读
    本类对象的引用作为参数,可以直接访问其私有成员
    构建完全二叉树、控制台打印二叉树
    转载:C++类内存分布
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4896301.html
Copyright © 2020-2023  润新知