UVA 10004 Bicoloring (二分染色)

题目链接:https://vjudge.net/problem/UVA-10004

题意:给你一个连通图,问能否将每个节点染成两种颜色之一,使得每条边两边的节点颜色不同。

(本质就是二分图的判定,有个定理是:一个无向图为二分图当且仅当图G中无奇数长度的回路。)

解题思路:

可以用dfs染色,对没有染过的点染色,如果该节点之前被染过且与当前要染的颜色不同那么就不能构成二分图。

dfs到了染过色的点记得return,否则有环的图会死循环的。

建边用了链式前向星

struct node
{
    int to,last;///to表示这条边的终点,last表示同一起点出发的上一条建的边的id
}edge[N<<1];
int head[N],id;///head[i]储存上一个节点i为起点的边(会随着建边不断更新)

void add(int u,int v)///建边
{
    edge[id].to = v;
    edge[id].last = head[u];
    head[u] = id++;
}

for (int i=head[now];i!=0;i=edge[i].last)///遍历

本题代码:

#include
#include
#include
#include
#define debug(x) printf("----Line %s----\n",#x)
using namespace std;

const int N = 2e2+5;

struct node
{
    int to,last;
}edge[N<<1];
int head[N],id;
int col[N];///节点颜色
bool flag;///是否可以二分染色

void add(int u,int v)
{
    edge[id].to = v;
    edge[id].last = head[u];
    head[u] = id++;
}

void dfs(int now,int pre,int color)///pre表示父节点
{
    if (~col[now] && col[now]!=color){
        flag = false;
        return ;
    }
    if (!flag) return ;
    if (~col[now]) return ;
    col[now] = color;
    color = (color==1 ? 2:1);
    for (int i=head[now];i!=0;i=edge[i].last){
        if (edge[i].to!=pre){
            dfs(edge[i].to,now,color);
        }
    }
}

int main()
{
    int n;
    while (scanf("%d",&n),n){
        int m;
        for (int i=1;i<=n;i++) head[i] = 0,col[i] = -1;///初始化
        //memset(head,0,sizeof head);
        //memset(col,-1,sizeof col);
        id = 1,flag = true;///初始化
        scanf("%d",&m);
        while (m--){
            int u,v;
            scanf("%d %d",&u,&v);
            u++,v++;
            add(u,v);//debug(1);
            add(v,u);
        }
        dfs(1,1,1);//debug(2);
        if (flag) printf("BICOLORABLE.\n");
        else printf("NOT BICOLORABLE.\n");
    }
    return 0;
}

 

你可能感兴趣的:(图论)