zoukankan      html  css  js  c++  java
  • HDU-1878 欧拉回路(并查集,欧拉回路性质)

    欧拉回路

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 15491    Accepted Submission(s): 5921

    Problem Description
    欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
     
    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
    束。
     
    Output
    每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
     
    Sample Input
    3 3 1 2 1 3 2 3 3 2 1 2 2 3 0
     
    Sample Output
    1 0
     
    Author
    ZJU
     
    Source
     
    Recommend
    We have carefully selected several similar problems for you:  1880 1881 1864 1873 1859 
    欧拉道路:若图G中存在一条道路,刚好经过所有的边一次,则成为欧拉道路,若经过所有边之后又回到原点,就是欧拉回路
    以下判断基于此图的基图连通。
    1.无向图存在欧拉回路的充要条件
             一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。
    2.有向图存在欧拉回路的充要条件
             一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。
    3.混合图存在欧拉回路条件
            要判断一个混合图G(V,E)(既有有向边又有无向边)是欧拉图,方法如下:
                    假设有一张图有向图G',在不论方向的情况下它与G同构。并且G'包含了G的所有有向边。那么如果存在一个图G'使得G'存在欧拉回路,那么G就存在欧拉回路。
                   其思路就将混合图转换成有向图判断。实现的时候,我们使用网络流的模型。现任意构造一个G'。用Ii表示第i个点的入度,Oi表示第i个点的出度。如果存在一个点k,|Ok-Ik|mod 2=1,那么G不存在欧拉回路。接下来则对于所有Ii>Oi的点从源点连到i一条容量为(Ii-Oi)/2的边,对于所有Ii<Oi的点从i连到汇点一条容量为(Oi-Ii)/2的边。如果对于节点U和V,无向边(U,V)∈E,那么U和V之间互相建立容量为无限大的边。如果此网络的最大流等于∑|Ii-Oi|/2,那么就存在欧拉回路。

    对于有向图,可以用并查集判断图是否连通,记录每一个顶点的度数来判读是否存在欧拉回路。
    代码:
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    const int N = 1000 + 5;
    int pre[N],in[N];
    int Find(int x){
        return pre[x]==x?x:(pre[x]=Find(pre[x]));
    }
    
    void Merge(int x,int y){
        x = Find(x),y=Find(y);
        if(x!=y) pre[x] = y;
    }
    
    int main(){
        int n,m;
        while(scanf("%d",&n)==1&&n){
            scanf("%d",&m);
            for(int i=1;i<=n;i++) pre[i] = i,in[i] = 0;
            int a,b;
            while(m--){
                scanf("%d %d",&a,&b);
                Merge(a,b);
                in[a]++; in[b]++;
            }
            bool is_euor = true;
            int cnt = 0;
            for(int i=1;i<=n;i++) if(pre[i]==i) cnt++;
            if(cnt > 1) {puts("0"); continue;}
            for(int i=1;i<=n;i++) if(in[i]&1) {is_euor = false; break;}
            printf("%d
    ",is_euor?1:0);
        }
        return 0;
    }


  • 相关阅读:
    Java核心技术 卷一 笔记四 库类的直接使用
    Java核心技术 卷一 笔记三 大数值及数组
    Java核心技术 卷一 笔记2 字符串的复制
    Java核心技术 卷一 笔记1
    修改css 样式后, hover事件 不生效
    修改 element ui input 输入框 样式不生效问题
    css3 计算属性
    Vue3 改动系列
    浏览器实现,向下滑动 鼠标滚轮,页面横向移动
    linux ceont0s7 vue 打包压缩图片 一直报错
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7384044.html
Copyright © 2011-2022 走看看