• UVALive 3523 : Knights of the Round Table (二分图+BCC)


    题目链接

    题意及题解参见lrj训练指南

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=1e3+5;
    int n,m;
    int dfn[maxn],low[maxn],time_tag;
    int bccno[maxn],bcc_cnt;
    int iscut[maxn];
    int A[maxn][maxn];
    vector<int> adj[maxn];
    vector<int> bcc[maxn];
    int odd[maxn];
    struct Edge
    {
        int u,v;
        Edge() {}
        Edge(int u_,int v_)
        {
            u=u_,v=v_;
        }
    };
    stack<Edge> st;
    void init()
    {
        memset(A,0,sizeof(A));
        memset(dfn,0,sizeof(dfn));
        memset(iscut,0,sizeof(iscut));
        memset(bccno,0,sizeof(bccno));
        memset(odd,0,sizeof(odd));
        for(int i=0; i<=n; i++)
            adj[i].clear(),bcc[i].clear();
        bcc_cnt=time_tag=0;
    }
    void dfs(int u,int pre)
    {
        low[u]=dfn[u]=++time_tag;
        int child=0; //子节点数目
        for(int v:adj[u])
        {
            if(v==pre) continue;
            if(!dfn[v]) // 把dfn[]当vis[]使用
            {
                st.push(Edge(u,v));
                child++;
                dfs(v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]>=dfn[u])
                {
                    iscut[u]=1;
                    bcc_cnt++;
                    while(1)
                    {
                        Edge x=st.top();st.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(dfn[v]<dfn[u])
            {
                st.push(Edge(u,v));
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(pre<0&&child==1) iscut[u]=0; //只有一个孩子的根节点
    }
    void find_bcc()
    {
        for(int i=0;i<n;i++)
            if(!dfn[i]) dfs(i,-1);
    }
    
    int color[maxn];
    //判定结点u所在的连通分量是否为二分图
    bool bipartite(int u,int tag)
    {
        for(int v:adj[u])
        {
            if(bccno[v]!=tag) continue;
            if(color[v]==color[u]) return false;
            if(!color[v])
            {
                color[v]=3-color[u];
                if(!bipartite(v,tag)) return false;
            }
        }
        return true;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)>0&&n)
        {
            init();
            for(int i=0;i<m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                u--,v--;
                A[u][v]=A[v][u]=1;
            }
            for(int u=0;u<n;u++)
                for(int v=u+1;v<n;v++)
                    if(!A[u][v])    adj[u].push_back(v),adj[v].push_back(u);
            find_bcc();
            for(int i=1;i<=bcc_cnt;i++)
            {
                memset(color,0,sizeof(color));
                for(int u:bcc[i]) bccno[u]=i;
                int u=bcc[i][0];
                color[u]=1;
                if(!bipartite(u,i))
                    for(int v:bcc[i]) odd[v]=1;
            }
            int ans=n;
            for(int i=0;i<n;i++) if(odd[i]) ans--;
            printf("%d
    ",ans); 
        }
    }
  • 相关阅读:
    md转html,并带目录结构
    vue05
    vue04
    mysql索引及调优
    mysql的锁与事务
    python基本数据类型的操作
    redis集群
    docker 学习(四)
    MongoDB基本操作
    MongoDB基础
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/7676553.html
Copyright © 2020-2023  润新知