• POJ


    题意:有N个人要参加会议,围圈而坐,需要举手表决,所以每次会议都必须是奇数个人参加。有M对人互相讨厌,他们的座位不能相邻。问有多少人任意一场会议都不能出席。

    分析:给出的M条关系是讨厌,将每个人视作点,在没有讨厌关系的人之间连边。

    问题中很重要的一点是:任意一场会议都不能参加。能够参加某一场会议就意味着,参加会议的人可以构成一个奇回路(他们要围圈而坐,且必须出席奇数个人)。那么问题就转化成了求有多少个点不在任意一个奇回路中。

    简单圈上的所有结点都属于同一个点双连通分量,因此找出所有的点双连通分量,并对该点双连通分量中判断其是否为二分图(二分图不含奇圈)。如果不是二分图,则表示其含有奇圈。打上标记,最后用点数N-没有被打上标记的点数,就是答案。

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<stack>
    using namespace std;
    const int maxn =1e3+5;
    const int maxm = 1e6+5;
    struct Edge{
        int to,next;
    }edges[maxm<<1];
    bool instack[maxn];
    int bccno[maxn],head[maxn],dfn[maxn],low[maxn],clk,top,scc;
    stack<int> S;
    int col[maxn];
    int ans;
    bool check[maxn];
    int tag[maxn];
    bool can[maxn];
    
    bool dfs(int u,int c)
    {
        col[u]=c;
        for(int i=head[u]; i!=-1; i=edges[i].next){
            int v=edges[i].to;
            if(!check[v])
                continue;
            if(col[v]!=-1){
                if(col[v]==c)
                    return false;
                continue;
            }
            if(!dfs(v,!c))
                return false;
        }
        return true;
    }
    void init()
    {
        clk = top = scc = 0;
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(bccno,0,sizeof(bccno));
        memset(instack,0,sizeof(instack));
        memset(can,0,sizeof(can));
    }
    
    void AddEdge(int u,int v)
    {
        edges[top].to = v;
        edges[top].next =head[u];
        head[u] = top++;
    }
    
    void Tarjan(int u,int id)
    {
        int v;
        low[u]=dfn[u]=++clk;
        S.push(u);
        instack[u]=true;
        for(int i=head[u];~i;i=edges[i].next){
            v = edges[i].to;
            if(i==(id^1))   continue;
            if(!dfn[v]){
                Tarjan(v,i);
                low[u]=min(low[u],low[v]);
                if(dfn[u]<=low[v]){     //找到一个双连通分量
                    scc++;                  //从1开始
                    int cnt=0;
                    memset(check,0,sizeof(check));         //判断是否在同一个双连通分量内
                    while(true){
                        int x =S.top();S.pop();
                        tag[cnt++] = x;
                        bccno[x]=scc;               //确定分量编号
                        instack[x]=false;
                        check[x] =true;
                        if(x==v)    break;      //找到了自己就要停止标号
                    }
                    check[u] = true;
                    memset(col,-1,sizeof(col));          //判断双连通分量内是否有奇圈
                    if(!dfs(u,0)){ 
                        can[u] = true;
                        while(cnt--)  can[tag[cnt]] = true;
                    }
                }
            }
            else if(instack[v])
                low[u]= min(low[u],dfn[v]);
        }
        
    }
    
    int G[maxn][maxn];
    
    int main()
    {
        #ifndef ONLINE_JUDGE
             freopen("in.txt","r",stdin);
             freopen("out.txt","w",stdout);
        #endif
        int T,N,M,u,v,tmp;
        while(scanf("%d%d",&N,&M)==2){
            if(!N) break;  
            init();
            memset(G,0,sizeof(G));
            for(int i=1;i<=M;++i){
                scanf("%d%d",&u,&v);
                G[u][v] = G[v][u] = 1;
            }
            for(int i=1;i<=N;++i){
                for(int j=i+1;j<=N;++j){
                    if(!G[i][j]){
                        AddEdge(i,j);
                        AddEdge(j,i);
                    }
                }
            }
            for(int i=1;i<=N;++i){
                if(!dfn[i])
                    Tarjan(i,-1);
            }
            ans= N;
            for(int i=1;i<=N;++i){
                if(can[i]) ans--;
            }
            printf("%d
    ",ans);    
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    Log4Net的使用之winform
    开源一个跨平台运行的服务插件
    定时管理器框架-Task.MainForm
    nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)
    关于SQL查询效率,100w数据,查询只要1秒
    写的一般,从起源到具体算法-深度学习综述
    如何避免SHRINKDATABASE & SHRINKFILE 产生索引碎片(转载)
    在windows service中启动类型“Automatic” 和 “Automatic (Delayed start)” 有何不同?
    C# 对WinForm应用程序的App.config的加密
    SQL Server中怎么查看每个数据库的日志大小,以及怎么确定数据库的日志文件,怎么用语句收缩日志文件
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9399944.html
Copyright © 2020-2023  润新知