UVA - 10004 Bicoloring(判断二分图——交叉染色法 / 带权并查集)

d.给定一个图,判断是不是二分图。

s.可以交叉染色,就是二分图;否则,不是。

另外,此题中的图是强连通图,即任意两点可达,从而dfs方法从一个点出发就能遍历整个图了。

如果不能保证从一个点出发可以遍历整个图,那么编程要注意了,应该从每个点出发遍历一次。

s2.带权并查集来判断,略复杂。先略过。先上个博客:http://blog.csdn.net/zsc09_leaf/article/details/6727622

c.邻接矩阵,bfs

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;

#define MAXN 205

int map[MAXN][MAXN];
int color[MAXN];
int n;

bool bfs(int start){//bfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0
    queue<int>q;
    color[start]=1;
    q.push(start);

    while(!q.empty()){
        int temp=q.front();
        q.pop();

        for(int i=0;i<n;++i){
            if(map[temp][i]){
                if(color[i]==0){//未染色
                    if(color[temp]==1){
                        color[i]=-1;
                    }
                    else{
                        color[i]=1;
                    }
                    q.push(i);
                }
                else{//已染色
                    if(color[i]==color[temp]){//相邻的两点颜色相同
                        return false;//不能交叉染色
                    }
                }
            }
        }
    }
    return true;
}

int main(){

    int L;
    int u,v;

    while(~scanf("%d",&n)){
        if(n==0)break;

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

        scanf("%d",&L);

        for(int i=0;i<L;++i){
            scanf("%d%d",&u,&v);

            map[u][v]=1;
            map[v][u]=1;
        }

        if(bfs(0)){
            printf("BICOLORABLE.\n");
        }
        else{
            printf("NOT BICOLORABLE.\n");
        }
    }

    return 0;
}

c2.邻接矩阵,dfs。这个图是强连通的,所以一次dfs可以遍历所有节点了。如果不是强连通的,则需要遍历多次。

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;

#define MAXN 205

int map[MAXN][MAXN];
int color[MAXN];
int n;

bool dfs(int u){//dfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0
    for(int i=0;i<n;++i){
        if(map[u][i]){
            if(color[i]==0){//未染色
                if(color[u]==1){
                    color[i]=-1;
                }
                else{
                    color[i]=1;
                }

                if(!dfs(i)){//不能交叉染色
                    return false;
                }
            }
            else{//已染色
                if(color[i]==color[u]){//不能交叉染色
                    return false;
                }
            }
        }
    }
    return true;
}

int main(){

    int L;
    int u,v;

    while(~scanf("%d",&n)){
        if(n==0)break;

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

        scanf("%d",&L);

        for(int i=0;i<L;++i){
            scanf("%d%d",&u,&v);

            map[u][v]=1;
            map[v][u]=1;
        }

        color[0]=1;
        if(dfs(0)){//这个图是强连通的,所以一次dfs可以遍历所有节点了。如果不是强连通的,则需要遍历多次。
            printf("BICOLORABLE.\n");
        }
        else{
            printf("NOT BICOLORABLE.\n");
        }
    }

    return 0;
}

c3.邻接表,bfs

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;

#define MAXN 205//点数
#define MAXM 10000//边数

int color[MAXN];

struct Edge{
    int to,next;
}edge[MAXM];

int head[MAXN];
int tot;

void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void init(){
    tot=0;
    memset(head,-1,sizeof(head));
}

bool bfs(int start){//bfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0
    int v;
    queue<int>q;
    color[start]=1;
    q.push(start);

    while(!q.empty()){
        int temp=q.front();
        q.pop();

        for(int i=head[temp];i!=-1;i=edge[i].next){//

            v=edge[i].to;

            if(color[v]==0){//未染色
                if(color[temp]==1){
                    color[v]=-1;
                }
                else{
                    color[v]=1;
                }
                q.push(v);
            }
            else{//已染色
                if(color[v]==color[temp]){//相邻的两点颜色相同
                    return false;//不能交叉染色
                }
            }

        }
    }
    return true;
}

int main(){

    int n,L;
    int u,v;

    while(~scanf("%d",&n)){
        if(n==0)break;

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

        scanf("%d",&L);

        for(int i=0;i<L;++i){
            scanf("%d%d",&u,&v);

            addedge(u,v);
            addedge(v,u);
        }

        if(bfs(0)){
            printf("BICOLORABLE.\n");
        }
        else{
            printf("NOT BICOLORABLE.\n");
        }
    }

    return 0;
}

c4.邻接表,dfs

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;

#define MAXN 205//点数
#define MAXM 10000//边数

int color[MAXN];

struct Edge{
    int to,next;
}edge[MAXM];

int head[MAXN];
int tot;

void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void init(){
    tot=0;
    memset(head,-1,sizeof(head));
}

bool dfs(int u){//dfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0

    int v;

    for(int i=head[u];i!=-1;i=edge[i].next){

        v=edge[i].to;

        if(color[v]==0){//未染色
            if(color[u]==1){
                color[v]=-1;
            }
            else{
                color[v]=1;
            }

            if(!dfs(v)){//不能交叉染色
                return false;
            }
        }
        else{//已染色
            if(color[v]==color[u]){//不能交叉染色
                return false;
            }
        }

    }
    return true;
}

int main(){

    int n,L;
    int u,v;

    while(~scanf("%d",&n)){
        if(n==0)break;

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

        scanf("%d",&L);

        for(int i=0;i<L;++i){
            scanf("%d%d",&u,&v);

            addedge(u,v);
            addedge(v,u);
        }

        color[0]=1;
        if(dfs(0)){
            printf("BICOLORABLE.\n");
        }
        else{
            printf("NOT BICOLORABLE.\n");
        }
    }

    return 0;
}

时间: 2024-10-29 10:45:59

UVA - 10004 Bicoloring(判断二分图——交叉染色法 / 带权并查集)的相关文章

hdu 1829 &amp;amp;poj 2492 A Bug&amp;#39;s Life(推断二分图、带权并查集)

A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8528    Accepted Submission(s): 2745 Problem Description Background  Professor Hopper is researching the sexual behavior of a rare

CodeForces - 687D: Dividing Kingdom II (二分图&amp;带权并查集)

Long time ago, there was a great kingdom and it was being ruled by The Great Arya and Pari The Great. These two had some problems about the numbers they like, so they decided to divide the great kingdom between themselves. The great kingdom consisted

HDU 3038 How Many Answers Are Wrong (带权并查集+区间判断)

题意:给你长度为n的区间,m个询问:a,b,c,问这m个问题有多少个是错误的(矛盾). 10 5 1 10 100 7 10 28 1 3 32 4 6 41 6 6 1 由6->6=1,  4->6=41 知4->5=40; 同理 由1->10=100,7->10=28 知1->7=72; 又由1->3=32,4-6=41 知1->7=73,与上面矛盾: 所以答案为1: #include<cstdio> #include<stdlib.h

UVA 12232 - Exclusive-OR(带权并查集)

UVA 12232 - Exclusive-OR 题目链接 题意:有n个数字.一開始值都不知道,每次给定一个操作,I a v表示确认a值为v,I a b v,表示确认a^b = v,Q k a1 a2 a3 ... ak.表示推断这些数字的异或值是否能确定.能确定就输出值,假设有矛盾就停止 思路:带权并查集,权表示和父结点的异或值,那么多数推断的时候,仅仅要全部数字和他的父结点的异或值的异或值.假设父结点的个数是偶数个.那么依据异或的性质能抵消掉,是能够判定的.假设不为偶数,就是不能判定. 注意

BZOJ4025 二分图 分治 并查集 二分图 并查集按秩合并 带权并查集

原文链接http://www.cnblogs.com/zhouzhendong/p/8683831.html 题目传送门 - BZOJ4025 题意 有$n$个点,有$m$条边.有$T$个时间段.其中第$i$条边连接节点$x_i,y_i$,并且在$start_i$时刻出现,在$end_i$时刻消失.问每一个时刻的图是不是二分图. $n\leq 10^5,m\leq 2\times 10^5,T\leq 10^5$ 题解 真是一道好题. 做这题我才发现我从来没写过按秩合并的并查集QAQ. 先考虑按

UVA 3027 Corporative Network 带权并查集、

题意:一个企业要去收购一些公司把,使的每个企业之间互联,刚开始每个公司互相独立 给出n个公司,两种操作 E I:询问I到I它连接点最后一个公司的距离 I I J:将I公司指向J公司,也就是J公司是I公司的上级,距离为abs(I-J)%1000(貌似G++不支持abs,PE了两发) 思路:转化一下题意就行了,首先刚开始的时候每个公司都是独立的,I操作就是并查集中合并操作,将I这课树并到J这个树上, E操作要求的东西就是 I到I的根节点的距离,先看一个没有路径压缩直接暴力的方法把.(本以为不会过的,

「UVA 11987」Almost Union-Find 「带权并查集」「思维」

你发现,这个第二个操作不可能用普通并查集来搞,很棘手 但是你考虑一下,并查集维护的是个森林结构,并且路径压缩的时候每个森林的根是不会变的, 也就是意味着每删掉一个点你需要让他的踪影消失匿迹即可,并不需要让他在原有的树结构上消失. 具体怎么消失?把贡献全在根上减掉即可,再新建一个新点连进去. 这个新点可以用id数组表示,即id[x]为x节点现在的编号. #include <bits/stdc++.h> #define test(...) fprintf(stderr, __VA_ARGS__)

交叉染色法判断二分图

题目链接:传送门 题目大意:给你一副无向联通图,判断是不是二分图 题目思路:交叉染色法 下面着重介绍下交叉染色法的定义与原理 首先任意取出一个顶点进行染色,和该节点相邻的点有三种情况: 1.未染色    那么继续染色此节点(染色为另一种颜色) 2.已染色但和当前节点颜色不同      跳过该点 3.已染色并且和当前节点颜色相同       返回失败(该图不是二分图) 下面在拓展两个概念: (1) 如果一个双连通分量内的某些顶点在一个奇圈中(即双连通分量含有奇圈),那么这个双连通分量的其他顶点也在

poj2942 双联通分量+交叉染色法判断二分图

Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 11805   Accepted: 3870 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the oth