zoukankan      html  css  js  c++  java
  • 欧拉路问题(学习笔记)

    欧拉路问题,俗称("一笔画"问题)

    定义:给定一张无向图,若存在一条从(S)(T)的路径,恰好不重不漏地经过每条边一次(可以重复经过图中的节点),则称该路径为(S)(T)的欧拉路.

    特别地,若存在一条从(S)出发的路径,恰好不重不漏地经过每条边一次(可以重复经过图中的节点),最终回到起点(S),则该路径为欧拉回路.

    存在欧拉回路的无向图称作欧拉图.

    欧拉图的判定:一张无向图为欧拉图,当且仅当无向图连通,并且每个点的度数都是偶数.

    欧拉路的存在性判定:一张无向图中存在欧拉路,当且仅当无向图连通,并且图中恰好有两个节点的度数为奇数,其它节点的度数都是偶数.这两个度数为奇数的点就是欧拉路的起点(S)和终点(T).

    inline void add(int a,int b){
    	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
    }
    inline void oula(){
    	st[++top]=1;//入栈
    	while(top>0){
    		int u=st[top],i=head[u];
    		while(i&&visit[i])i=nxt[i];//找到一条没有被访问过的边
    		if(i){
    			st[++top]=to[i];
    			visit[i]=visit[i^1]=1;
    //标记为访问过,这里体现了tot=1的好处,每一条边被两个方向存储
    //数组下标一定是2,3或者4,5这种异或1能够互相得到的
    			head[u]=nxt[i];
    		}
    		else --top,ans[++sum]=u;
    //u相连的所有边均被访问过,则回溯.
    	}
    }
    int main(){
    	int n=read(),m=read();tot=1;
    	for(int i=1;i<=m;++i){
    		int a=read(),b=read();
    		add(a,b);add(b,a);
    	}
    	oula();
    	for(int i=sum;i>=1;--i)printf("%d
    ",ans[i]);//倒序输出
    }
    
    

    POJ,来一道模板题练练手.

    题意:给定(N(N<=10000))个点(M(M<=50000))条边的无向图,求一条路径,从节点1出发,最后回到节点1,并且满足每条边恰好被正反两个方向分别经过一次.若有多种方案,输出任意一种即可.

    分析:求欧拉回路的问题.在上述模板的基础上,去掉(visit)数组的标记即可保证每条边恰好被正反两个方向分别经过一次.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=100005;
    int n,m;
    int top,sum,st[N],ans[N];
    int tot,head[N],nxt[N],to[N];
    inline void add(int a,int b){
    	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
    }
    inline void oula(){
    	st[++top]=1;
    	while(top>0){
    		int u=st[top],i=head[u];
    		if(i){
    			st[++top]=to[i];
    			head[u]=nxt[i];
    		}
    		else --top,ans[++sum]=u;
    	}
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=m;++i){
    		int a=read(),b=read();
    		add(a,b);add(b,a);
    	}
    	oula();
    	for(int i=sum;i>=1;--i)printf("%d
    ",ans[i]);
        return 0;
    }
    
    
  • 相关阅读:
    UPC 5130 Concerts
    poj 1079 Calendar Game
    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛
    CF932E
    浅谈Tarjan算法
    拉格朗日差值
    扩展欧几里得算法(exgcd)
    欧拉定理
    莫比乌斯反演
    除法分块
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11575334.html
Copyright © 2011-2022 走看看