• poj 2942 求点双联通+二分图判断奇偶环+交叉染色法判断二分图


    http://blog.csdn.net/lyy289065406/article/details/6756821
    http://www.cnblogs.com/wuyiqi/archive/2011/10/19/2217911.html
    
    #include "stdio.h"
    #include "string.h"
    
    #define N 1010
    
    int time;
    int n,m;
    bool map[N][N];
    
    struct node
    {
        int x,y;
        //int weight;
        bool visit;  //用来标记该边是否已经访问
        int next;
    }edge[2*N*N];
    int idx,head[N];
    
    bool odd[N];
    bool mark[N];  //标记点是否为当前双连通分量中的元素
    int low[N],dfn[N];
    int st[N*N],top;  //模拟栈
    int col[N];
    
    void Read_date();
    inline int MIN(int a,int b) { return a<b?a:b; }
    void Init(){ idx=0; memset(head,-1,sizeof(head)); }
    void Add(int x,int y)
    {
        edge[idx].x = x;
        edge[idx].y = y;
        edge[idx].visit = false;
        edge[idx].next = head[x];
        head[x] = idx++;
    }
    
    bool find(int x)   //判断当前双连通分量是否为二分图
    {
        int i,y;
        for(i=head[x]; i!=-1; i=edge[i].next)
        {
            y = edge[i].y;
            if(mark[y])
            {
                if(col[y]==-1)
                {
                    col[y] = !col[x];
                    return find(y);
                }
                else if(col[y]==col[x])
                    return false;  //不是二分图,返回false
            }
        }
        return true; //是二分图,返回true
    }
    
    void Color(int x)
    {
        int i;
        memset(mark,false,sizeof(mark));
        while(1)
        {
            i = st[top];
            top--;
            mark[edge[i].x] = true;
            mark[edge[i].y] = true;
            if(edge[i].x==x) break;
        }
        memset(col,-1,sizeof(col));
        col[x] = 0;
        if(!find(x))  //双连通分量不是二分图,则这些点全部可以
        {
            for(i=1; i<=n; ++i)
            {
                if(mark[i])
                    odd[i] = 1;
            }
        }
    }
    
    void DFS(int x)
    {
        int i,y;
        low[x] = dfn[x] = ++time;
        for(i=head[x]; i!=-1; i=edge[i].next)
        {
            y = edge[i].y;
            if(edge[i].visit) continue;
            edge[i].visit = edge[i^1].visit = 1;//走过的边不能再走了
            st[++top] = i;
            if(!dfn[y])
            {
                DFS(y);
                low[x] = MIN(low[x],low[y]);
                if(low[y]>=dfn[x])   //找到割顶或者为根节点
                    Color(x);
            }
            else
                low[x] = MIN(low[x],dfn[y]);
        }
    }
    
    int Solve()
    {
        int i;
        int num=0;
        time = 0;
        top = 0;
        memset(dfn,0,sizeof(dfn));
        memset(odd,false,sizeof(odd));
        for(i=1; i<=n; ++i)
        {
            if(!dfn[i])  //表示点i未被访问过
                DFS(i); //以i为根节点找双连通分量
        }
        for(i=1; i<=n; ++i)
        {
            if(!odd[i])
                num++;
        }
        return num;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m),n||m)
        {
            Read_date();
            printf("%d
    ",Solve());
        }
        return 0;
    }
    
    void Read_date()
    {
        int i,j;
        int x,y;
        memset(map,true,sizeof(map));
        while(m--)
        {
            scanf("%d %d",&x,&y);
            map[x][y] = map[y][x] = false;
        }
        Init();
        for(i=1; i<=n; ++i)
        {
            for(j=i+1; j<=n; ++j)
            {
                if(map[i][j])
                {
                    Add(i,j);
                    Add(j,i);
                }
            }
        }
    }
    
    
    
    
    
    

  • 相关阅读:
    JDK安装与配置
    MAVEN安装与配置
    http协议与soap协议之间的区别
    Zookeeper
    TCP/IP及http协议 SOAP REST
    Java数据结构总述
    SQL基础
    IntelliJ IDEA 快捷键
    反射机制
    java集合的作用
  • 原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410684.html
Copyright © 2020-2023  润新知