[图论模型] hdu4751 二分图及二分图判断

二分图

这里写图片描述
二分图,图论中的一种特殊模型。设 G = ( V , E ) 是一个无向图,如果顶点 V 可以分割成两个互不相交的子集 ( U , V ) ,并且图中的每条边 ( i , j ) 所关联的两个顶点分别属于这两个不同的顶点集 ( i   i n   U , j   i n   V ) ,则称图G为一个二分图。


二分图的判定条件:
1.G至少有两个顶点。
2.所有回路的长度均为偶数。

可以将 U 和 V 当做 着色图: U 中所有节点为蓝色, V 中所有节点着绿色,每条边的两个端点的颜色不同,符合图着色问题的要求。相反,用这样的着色方式对非二分图是行不通的,根据triangle:其中一个顶点着蓝色并且另一个着绿色后,三角形的第三个顶点与上述具有两个颜色的顶点相连,无法再对其着蓝色或绿色。

二分图判断

交叉染色。
给一个无向图。要给图上每个顶点染色,并且使任意相邻的顶点染色不同。并且最多用两种颜色。如果可以进行二分图染色,证明是一个二分图。

题目

hdu4751,一堆人,每个人单方面认识一些人,希望把这些人分成两堆,使得每一堆的人都相互认识。

思路

若能分出两堆,A不认识B,B不认识C,则必然有A认识C。
所以根据不认识关系建立图,判断是否为二分图即可。

代码(二分图判断模板)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 100 + 10;
int n, knows[maxn][maxn], G[maxn][maxn], color[maxn];

bool dfs(int u, int c) {
    color[u] = c;
    _rep(v,1,n)
        if (G[u][v] && v != u) {
            if (color[v] == c) return false;
            if (color[v] == 0 && !dfs(v, -c)) return false;
        }
    return true;
}

bool solve() {
    _rep(i, 1, n)
        if (color[i] == 0 && !dfs(i, 1))
            return false;
    return true;
}

int main() {
    while (scanf("%d", &n) == 1 && n) {
        int v;
        memset(knows, 0, sizeof(knows));
        _rep(u, 1, n) {
            while (1) {
                scanf("%d", &v);
                if (v == 0) break;
                knows[u][v] = 1;
            }
        }
        memset(G, 0, sizeof(G));
        _rep(u,1,n)
            _rep(v,1,n)
                if (!knows[u][v] || !knows[v][u])
                    G[u][v] = G[v][u] = 1;

        memset(color, 0, sizeof(color));

        if (solve()) printf("YES\n");
        else printf("NO\n");
    }

    return 0;
}

本题实际是在为团队分组那道题做铺垫。

猜你喜欢

转载自blog.csdn.net/icecab/article/details/81040934
今日推荐