• hdoj 3478 Catch(二分图判定+并查集)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3478

    思路分析:该问题需要求是否存在某一个时刻,thief可能存在图中没一个点;将该问题转换为图论问题即为判断该图是否为一个连通图且不为二分图;

    (1)二分图的性质:对于无向图G=(V, E),如果可以将图中的点划分为两个不相交的点集X与Y = V - X(V为点集),使得图中所有的边邻接的两个点分别存在集合X与集合Y中,则称该图G为二分图;

    (2) 二分图判定算法:二分图一种判定方法是给图中的每一个点着黑色或者白色,如果图中每条边邻接的两个点的颜色不同,则该图为二分图,所以非联通的图也可以是二分图,即一个无向图是二分图当且仅当其每个联通分量都是二分图;二分图判定算法使用dfs搜索:选定一个起始结点并着以某一种颜色,从该起始结点出发,与其邻接的点如果已经着色并且颜色与该结点相同,则不为二分图,如果与其邻接的点没有着色,则对该点着以不同的颜色,如此处理直到所有的点被着色成功则该结点所在的联通分量为二分图;需要注意的是图中可能有多个联通分量;

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <iostream>
    using namespace std;
    
    const int MAX_N = 100000 + 100;
    vector<int> G[MAX_N];
    int fa[MAX_N], color[MAX_N];
    
    void Init()
    {
        for (int i = 0; i < MAX_N; ++i)
        {
            fa[i] = i;
            G[i].clear( );
        }
        memset(color, 0, sizeof(color));
    }
    
    int Find(int v)
    {
        if (fa[v] == v)
            return v;
        else
            return fa[v] = Find(fa[v]);
    }
    
    int Union(int a, int b)
    {
        int fa_a = Find(a);
        int fa_b = Find(b);
    
        if (fa_a == fa_b)
            return -1;
        else if (fa_a > fa_b)
            fa[fa_b] = fa_a;
        else
            fa[fa_a] = fa_b;
        return 1;
    }
    
    bool BiPartite(int u)
    {
        for (int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            if (color[u] == color[v])
                return false;
            if (!color[v])
            {
                color[v] = 3 - color[u];
                if (!BiPartite(v))
                    return false;
            }
        }
        return true;
    }
    
    int main()
    {
        int test_case, ver_1, ver_2;
        int ver_num, road_num, start, case_id = 0;
    
        scanf("%d", &test_case);
        while (test_case--)
        {
            Init();
            scanf("%d %d %d", &ver_num, &road_num, &start);
            for (int i = 0; i < road_num; ++i)
            {
                scanf("%d %d", &ver_1, &ver_2);
                G[ver_1].push_back(ver_2);
                G[ver_2].push_back(ver_1);
                Union(ver_1, ver_2);
            }
    
            int set_count = 0;
            for (int i = 0; i < ver_num; ++i)
            {
                if (fa[i] == i)
                    set_count++;
                if (set_count > 1)
                    break;
            }
            printf("Case %d: ", ++case_id);
            color[start] = 1;
            if (!BiPartite(start) && set_count == 1)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    html 页面打印元素被切割,元素自适应分页
    linux jupyter 安装
    == 与 equals()的区别
    多段图
    数据仓库和ODS 的并行
    Linux下对sh文件的基本操作总结
    linux tr命令详解
    数据仓库分层
    利用SQOOP将数据从数据库导入到HDFS(并行导入,增量导入)
    Etl之HiveSql调优(left join where的位置)
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4672718.html
Copyright © 2020-2023  润新知