zoukankan      html  css  js  c++  java
  • Euler回路

    首先都要判断连通性。

    无向图Euler回路

    一个无向图有Euler回路(Leftrightarrow)每个点的度数为偶数。
    求Euler回路可以采用套圈法。
    过程就是dfs,回溯的时候把边加到答案里面去。

    有向图Euler回路

    一个有向图有Euler回路(Leftrightarrow)每个点的出度等于入度。
    求Euler回路过程跟无向图是一样的。

    混合图Euler回路

    就是有的边是无向边有的边是有向边。
    我们先给原图(G)中的无向边随便定个向,得到一个新图(G')
    那么如果(G')中的任意一个点的出度减入度(记为(d_i))为奇数,那么不存在Euler回路。
    然后我们建一个图(G'')跑网络流。
    建一个源点(S)和汇点(T)
    (forall d_i>0)连一条(S)(i)的容量为(frac{d_i}2)的边。
    (forall d_i<0)连一条(i)(T)的容量为(frac{-d_i}2)的边。
    然后把(G')中的所有边加到(G'')来,容量为(1)
    (G'')的最大流,如果(S)连出去的边都能满流,那么(G)存在Euler回路。
    正确性很好理解,因为这个(G'')的意义就是凑出每个点入度等于出度的无向图。
    然后把(G'')中在(G)中为无向边的流量为(1)的边中有流量的边反向,那么就形成了一个能存在Euler回路的有向图。所以要求方案就可以直接在这个有向图上面求了。

    例题

    UOJ117 欧拉回路
    Link

    #include<bits/stdc++.h>
    using namespace std;
    namespace IO
    {
        char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
        void Put(char x){*oS++=x;if(oS==oT)Flush();}
        int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
        void write(int x){int top=0;if(x<0)Put('-'),x=-x;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(' ');}
    }
    using IO::read;
    using IO::write;
    #define N 100007
    int tot=1,head[N],ver[N<<2],Next[N<<2],deg[N],vis[N<<2],ans[N<<2],num;
    void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
    int cal(int x){return x%2? -x/2:x/2;}
    void dfs(int u)
    {
        int i;
        while(head[u])
    	if(!vis[i=head[u]]) vis[i]=vis[i^1]=1,dfs(ver[i]),ans[++num]=cal(i);
    	else head[u]=Next[head[u]];
    }
    int solve1()
    {
        int n=read(),m=read(),i,u,v;
        for(i=1;i<=m;++i) u=read(),v=read(),add(u,v),add(v,u),++deg[u],++deg[v];
        for(i=1;i<=n;++i) if(deg[i]%2) return 0;
        for(i=1;i<=n;++i) if(head[i]) {dfs(i);break;}
        if(num^m) return 0;
        puts("YES");
        for(;num;--num) write(ans[num]);
        return 1;
    }
    void Dfs(int u)
    {
        int i;
        while(head[u])
    	if(!vis[i=head[u]]) vis[i]=1,Dfs(ver[i]),ans[++num]=i-1;
    	else head[u]=Next[head[u]];
    }
    int solve2()
    {
        int n=read(),m=read(),i,u,v;
        for(i=1;i<=m;++i) u=read(),v=read(),add(u,v),--deg[u],++deg[v];
        for(i=1;i<=n;++i) if(deg[i]) return 0;
        for(i=1;i<=n;++i) if(head[i]) {Dfs(i);break;}
        if(num^m) return 0;
        puts("YES");
        for(;num;--num) write(ans[num]);
        return 1;
    }
    int main()
    {
        if(read()==1? solve1():solve2()) return IO::Flush(),0;
        else return !puts("NO");
    }
    
  • 相关阅读:
    我是如何基于angular+requirejs+node做SPA项目架构的
    阿里云无线&前端团队是如何基于webpack实现前端工程化的
    angularjs源码分析之:angularjs执行流程
    你所必须掌握的三种异步编程方法callbacks,listeners,promise
    自从用了Less 编写css,你比以前更快了~
    对象的深浅拷贝
    throttle/debounce: 为你的cpu减减压(前端性能优化)
    jekyll : 使用github托管你的博客
    html5 drag api详解
    用setTimeout 代替 setInterval实时拉取数据
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11924431.html
Copyright © 2011-2022 走看看