Bicoloring——交叉染色

  Bicoloring 

In 1976 the ``Four Color Map Theorem" was proven with the assistance of a computer. This theorem states that every map can be colored using only four colors, in such a way that no region is colored using the same color as a neighbor region.

Here you are asked to solve a simpler similar problem. You have to decide whether a given arbitrary connected graph can be bicolored. That is, if one can assign colors (from a palette of two) to the nodes in such a way that no two adjacent nodes have the same color. To simplify the problem you can assume:

  • no node will have an edge to itself.
  • the graph is nondirected. That is, if a node a is said to be connected to a node b, then you must assume that b is connected to a.
  • the graph will be strongly connected. That is, there will be at least one path from any node to any other node.

Input 

The input consists of several test cases. Each test case starts with a line containing the number  n  (  1 <  n  < 200) of different nodes. The second line contains the number of edges  l . After this,  l  lines will follow, each containing two numbers that specify an edge between the two nodes that they represent. A node in the graph will be labeled using a number  a  (  $0 \le a < n$ ).

An input with n = 0 will mark the end of the input and is not to be processed.

Output 

You have to decide whether the input graph can be bicolored or not, and print it as shown below.

Sample Input 

3
3
0 1
1 2
2 0
9
8
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0

Sample Output 

NOT BICOLORABLE.
BICOLORABLE.


题意:给出从0开始的n个点,对这些点进行染色,相邻的点不能染相同的颜色,而且只有两种颜色。问能不能染色成功?

解析:用两种方法做出这个题目,一个是BFS遍历查找,一个是并查集。

首先将整个图用邻接矩阵存储图,两点相连记为1,将0点放入队列中,然后遍历其他和0点相邻的点,依次标记为0点的对立颜色,然后将这些点进队列,再次遍历,如果发现两点相连,并且都已经被标记过,且标记颜色相同,那么就不能完成涂色,直接退出BFS就好。


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>

using namespace std;

int mapp[206][206],color[209],bj = 0,n,m;

void bfs()
{
    int y;
    queue<int>q;
    q.push(0);
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        for(y = 0; y < n; y++)
        {
            if(mapp[x][y])
            {
                if(color[y] == 0)
                {
                    if(color[x] == 1)
                        color[y] = 2;
                    if(color[x] == 2)
                        color[y] = 1;
                    q.push(y);
                }
                else if(color[x] == color[y])
                {
                    bj = 1;
                    return ;
                }
            }
        }
    }
}

int main()
{
    int i,j;
    while(~scanf("%d",&n),n)
    {
        memset(mapp,0,sizeof(mapp));
        memset(color,0,sizeof(color));
        scanf("%d",&m);
        bj = 0;
        while(m--)
        {
            scanf("%d%d",&i,&j);
            mapp[i][j] = 1;
            mapp[j][i] = 1;
        }
        color[0] = 1;
        bfs();
        if(bj == 1)
            printf("NOT BICOLORABLE.\n");
        else
            printf("BICOLORABLE.\n");
    }
    return 0;
}


接下来用并查集来实现一下

我们都知道,并查集是用来存储在同一个集合中的元素关系的,而这道题目是给出的两个数不在同一个集合中,但是这道题目有一个很凑巧的地方,那就是中有两种颜色,所以如果a与b异色,b与c异色,那么a_b_c中,a,c一定是同一种颜色,所以可以将不在同一个集合中的元素依次连接起来,在查找两个元素能不能同色的时候,就看两个元素之间相隔的元素个数的奇偶,基数的话一定是同色,偶数的话一定是异色。

让我们来看一下代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define Size 10000

using namespace std;
int bj[1000];

int find(int x,int &s)
{
    s = 0;
    while(bj[x] != x)
    {
        x = bj[x];
        s++;
    }
    return x;
}

int unio(int x,int y)
{
    int step1,step2;
    int fx = find(x,step1);
    int fy = find(y,step2);
    if(fx == fy)
    {
        if(abs(step1-step2-1)%2==1)
            return 0;
    }
    else
    {
        bj[fx] = fy;
    }
    return 1;
}

int main()
{
    int n,m,i,j,u,v;
    while(~scanf("%d",&n),n)
    {
        scanf("%d",&m);
        for(i = 0; i <= n; i++)
        {
            bj[i] = i;
        }
        int c = 1;
        for(i = 0; i < m; i++)
        {
            scanf("%d%d",&u,&v);
            if(c)
                c = unio(u,v);
        }
        if(c)
            printf("BICOLORABLE.\n");
        else
            printf("NOT BICOLORABLE.\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值