HDU5215---Cycle(染色法判定奇偶环)

题目来源:http://acm.hdu.edu.cn/php?pid=5215

题意

给出一个无向图,判定这个无向图中是否存在奇偶环。

思路

利用染色法去枚举该点以及他周围所有点,利用反祖边的思想,那么若是存在反祖边,就要判断一下颜色,若是一样,则是构不成二分图,也表明是奇环,反之,则是偶环,但是有一种偶环是奇环拼凑起来的,比如:
HDU5215---Cycle(染色法判定奇偶环)_第1张图片
这里,假如,染色的时候是按着:1->2->3的顺序,到了3之后,发现了反祖边,通过颜色对比表明1->2->3->1是奇环那么我将点1记录下来,然后,遍历3->4,发现了反祖边,在判断是奇环,此时,反着遍历这条奇环,枚举各点,发现1被标记过,也就是1存在于另外一个奇环里,那么这两个奇环就会成为一个偶环。。。

代码

#include
#include
#include
using namespace std;
struct pp
{
    int  to,next;
}edge[300000+10];
int first[100000+10];
int color[100000+10];
int flag[100000+10];
int parent[100000+10];
int n,m,tot,even,odd;
void add(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=first[u];
    first[u]=tot++;
}
bool dfs(int u)
{
    for(int i=first[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==parent[u]) continue;
        if(color[v]!=-1)
        {
            if(color[v]!=color[u])
            {
                even=1;
            }
            else
            {
                odd=1;
                int x=v;
                while(!even)
                {
                    if(flag[x])
                    {
                        even=1;
                        break;
                    }
                    flag[x]++;
                    x=parent[x];//遍历
                    if(x==u||x==-1) break;//临界点
                }
            }
            continue;
        }
        color[v]=color[u]^1;
        parent[v]=u;
        dfs(v);
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        tot=0;
        scanf("%d%d",&n,&m);
        memset(first,-1,sizeof(first));
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        even=0,odd=0;
        memset(color,-1,sizeof(color));
        memset(flag,0,sizeof(flag));
        memset(parent,-1,sizeof(parent));
        for(int i=1;i<=n;i++)
        {
            if(color[i]==-1)
            {
                color[i]=1;
                dfs(i);
            }
        }
        puts(odd?"YES":"NO");
        puts(even?"YES":"NO");
    }
}

你可能感兴趣的:(ACM竞赛,【含有一定技巧】,【图论】--二分图匹配,ACM的进程)