zoukankan      html  css  js  c++  java
  • 欧拉回路与欧拉路径

    概念

    欧拉路径指一条所有边都经过且只有一次的路径
    如果起点和终点相同就是欧拉回路

    判定

    有向图:所有点连通,且入度都等于出度,则有欧拉回路
    无向图:所有点连通,且度数为偶数,则有欧拉回路
    显然欧拉回路删掉一条边就是欧拉路径
    那么欧拉路径中有且只有两个不符合欧拉回路要求的点,并且相连后就满足了

    算法

    求欧拉路径就把不满足的点连起来,求欧拉回路后删掉这条边就好了

    无向图

    (dfs),标记走过的边以及反边,走过就不走
    每次回溯时记录边,这些边依次构成欧拉回路

    有向图

    边反向,(dfs)标记走过的边,每次回溯时记录边,这些边依次构成欧拉回路

    都差不多,然后可以当前弧优化

    正确性

    除了第一个点外,其它的点(dfs)是一定是入边出边成对出现
    所以第一次加入答案的边一定是第一个点的入边
    回溯时这个点又会多走一条出边,那么下次加入的一定是又是这个点的入边
    归纳下去,一定会形成一条回路

    代码

    (UOJ)模板

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(4e5 + 5);
    typedef int Arr[_];
    
    IL int Input(){
        RG int x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    Arr first, cur, vis, ans, rd, od;
    int n, m, cnt, num;
    struct Edge{
        int to, next, id;
    } edge[_];
    
    IL void Add1(RG int u, RG int v, RG int id){
    	++rd[u], ++rd[v];
        edge[cnt] = (Edge){v, first[u], id}, first[u] = cnt++;
        edge[cnt] = (Edge){u, first[v], -id}, first[v] = cnt++;
    }
    
    IL void Dfs1(RG int u){
    	for(RG int &e = cur[u]; e != -1; e = edge[e].next){
    		if(vis[e]) continue;
    		RG int tmp = e; vis[e] = vis[e ^ 1] = 1;
    		Dfs1(edge[e].to);
    		ans[++num] = edge[tmp ^ 1].id;
    		if(e == -1) return;
    	}
    }
    
    IL void Work1(){
    	Fill(first, -1), n = Input(), m = Input();
    	for(RG int i = 1, u, v; i <= m; ++i) u = Input(), v = Input(), Add1(u, v, i);
    	for(RG int i = 1; i <= n; ++i){
    		cur[i] = first[i];
    		if(rd[i] & 1){
    			puts("NO");
    			return;
    		}
    	}
    	for(RG int i = 1; i <= n; ++i)
    		if(rd[i]){
    			Dfs1(i);
    			break;
    		}
    	if(num != m){
    		puts("NO");
    		return;
    	}
    	puts("YES");
    	for(RG int i = 1; i <= m; ++i) printf("%d ", ans[i]);
    	puts("");
    }
    
    IL void Add2(RG int u, RG int v, RG int id){
    	++rd[v], ++od[u];
        edge[cnt] = (Edge){v, first[u], id}, first[u] = cnt++;
    }
    
    IL void Dfs2(RG int u){
    	for(RG int &e = cur[u]; e != -1; e = edge[e].next){
    		if(vis[e]) continue;
    		RG int tmp = e; vis[e] = 1;
    		Dfs2(edge[e].to);
    		ans[++num] = edge[tmp].id;
    		if(e == -1) return;
    	}
    }
    
    IL void Work2(){
    	Fill(first, -1), n = Input(), m = Input();
    	for(RG int i = 1, u, v; i <= m; ++i) u = Input(), v = Input(), Add2(v, u, i);
    	for(RG int i = 1; i <= n; ++i){
    		cur[i] = first[i];
    		if(rd[i] != od[i]){
    			puts("NO");
    			return;
    		}
    	}
    	for(RG int i = 1; i <= n; ++i)
    		if(od[i]){
    			Dfs2(i);
    			break;
    		}
    	if(num != m){
    		puts("NO");
    		return;
    	}
    	puts("YES");
    	for(RG int i = 1; i <= m; ++i) printf("%d ", ans[i]);
    	puts("");
    }
    
    int main(RG int argc, RG char *argv[]){
    	Input() == 1 ? Work1() : Work2();
        return 0;
    }
    
    
  • 相关阅读:
    TortoiseCVS + 错误 + 无效句柄:解决方法
    Oracle学习笔记:关于Oracle服务器在windows32位平台上连接数受限制的问题
    IE6 很邪恶,但我爱它的盒子模型
    PHP环境搭建:Windows 7下安装配置PHP+Apache+Mysql环境教程
    关于跨浏览器测试那点事
    【转】IETester更新至最新版已经兼容Windows7(附下载地址及Debugbar插件)
    Web 设计师的 50 个超便利工具(上)
    各大浏览器 CSS3 和 HTML5 兼容速查表
    15 个 JavaScript Web UI 库
    编写跨浏览器兼容的 CSS 代码的金科玉律
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8663584.html
Copyright © 2011-2022 走看看