• UVA-10735


    题意:给你一个图,有N个点,M条边,这M条边有的是单向的,有的是双向的.

    问你能否找出一条欧拉回路,使得每条边都只经过一次!

    分析:

    下面转自别人的题解:

    把该图的无向边随便定向,然后计算每个点的入度和出度。如果有某个点出入度之差为奇数,那么肯定不存在欧拉回路。因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。

     
      好了,现在每个点入度和出度之差均为偶数。那么将这个偶数除以2,得x。也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入。如果每个点都是出 = 入,那么很明显,该图就存在欧拉回路。 


      现在的问题就变成了:我该改变哪些边,可以让每个点出 = 入?构造网络流模型。首先,有向边是不能改变方向的,要之无用,删。一开始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样,边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。之后,察看是否有满流的分配。有就是能有欧拉回路,没有就是没有。欧拉回路是哪个?察看流值分配,将所有流量非 0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 = 出度的欧拉图。 
      由于是满流,所以每个入 > 出的点,都有x条边进来,将这些进来的边反向,OK,入 = 出了。对于出 > 入的点亦然。那么,没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点,自然早在开始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。 
    所以,就这样,混合图欧拉回路问题,解了。 

    // File Name: 10735.cpp
    // Author: Zlbing
    // Created Time: 2013/6/18 21:46:23
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    const int MAXN=125;
        int n,m;
    struct Edge2{
        int from,to;
    };
    vector<Edge2> edges2;
    vector<int> G2[MAXN];
    struct Edge{
        int from,to,cap,flow;
    };
    bool cmp(const Edge& a,const Edge& b){
        return a.from < b.from || (a.from == b.from && a.to < b.to);
    }
    struct Dinic{
        int n,m,s,t;
        vector<Edge> edges;
        vector<int> G[MAXN];
        bool vis[MAXN];
        int d[MAXN];
        int cur[MAXN];
        void init(int n){
            this->n=n;
            for(int i=0;i<=n;i++)G[i].clear();
            edges.clear();
        }
        void AddEdge(int from,int to,int cap){
            edges.push_back((Edge){from,to,cap,0});
            edges.push_back((Edge){to,from,0,0});//当是无向图时,反向边容量也是cap,有向边时,反向边容量是0
            m=edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
        bool BFS(){
            CL(vis,0);
            queue<int> Q;
            Q.push(s);
            d[s]=0;
            vis[s]=1;
            while(!Q.empty()){
                int x=Q.front();
                Q.pop();
                for(int i=0;i<G[x].size();i++){
                    Edge& e=edges[G[x][i]];
                    if(!vis[e.to]&&e.cap>e.flow){
                        vis[e.to]=1;
                        d[e.to]=d[x]+1;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
        int DFS(int x,int a){
            if(x==t||a==0)return a;
            int flow=0,f;
            for(int& i=cur[x];i<G[x].size();i++){
                Edge& e=edges[G[x][i]];
                if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
                    e.flow+=f;
                    edges[G[x][i]^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if(a==0)break;
                }
            }
            return flow;
        }
        //当所求流量大于need时就退出,降低时间
        int Maxflow(int s,int t,int need){
            this->s=s;this->t=t;
            int flow=0;
            while(BFS()){
                CL(cur,0);
                flow+=DFS(s,INF);
                if(flow>need)return flow;
            }
            return flow;
        }
        //最小割割边
        vector<int> Mincut(){
            BFS();
            vector<int> ans;
            for(int i=0;i<edges.size();i++){
                Edge& e=edges[i];
                if(vis[e.from]&&!vis[e.to]&&e.cap>0)ans.push_back(i);
            }
            return ans;
        }
        void Reduce(){
            for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
        }
        void ClearFlow(){
            for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
        }
    };
    
    Dinic solver;
    int in[MAXN],out[MAXN];
    stack<int> S;
    int vis[MAXN*MAXN];
    void build()
    {
        for(int i=0;i<solver.edges.size();i++)
        {
            Edge e=solver.edges[i];
            if(e.from>=1&&e.from<=n&&e.to>=1&&e.to<=n&&e.cap>0)
            {
                if(e.flow)
                {
                    edges2.push_back((Edge2){e.to,e.from});
                    int mm=edges2.size();
                    G2[e.to].push_back(mm-1);
                }
                else
                {
                    edges2.push_back((Edge2){e.from,e.to});
                    int mm=edges2.size();
                    G2[e.from].push_back(mm-1);
                }
            }
        }
    }
    void dfs(int u)
    {
                //printf("u=%d 
    ",u);
        for(int i=0;i<G2[u].size();i++)
        {
            int mm=G2[u][i];
            Edge2 e=edges2[mm];
            int v=e.to;
                //printf("aau=%d v=%d
    ",u,v);
            if(!vis[mm])
            {
                //printf("u=%d v=%d
    ",u,v);
                vis[mm]=1;
                dfs(v);
            }
        }
        S.push(u);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++)
        {
            scanf("%d%d",&n,&m);
            solver.init(n+2);
            int s=0,t=n+1;
            for(int i=0;i<=n;i++)G2[i].clear();
            edges2.clear();
            CL(in,0);
            CL(out,0);
            int a,b;char c[10];
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%s",&a,&b,c);
                if(c[0]=='D'){
                    edges2.push_back((Edge2){a,b});
                    int mm=edges2.size();
                    G2[a].push_back(mm-1);
                    in[b]++;out[a]++;
                }
                else if(c[0]=='U')
                {
                    solver.AddEdge(a,b,1);    
                    in[b]++;out[a]++;
                }
            }
            bool flag=true;
            for(int i=1;i<=n;i++)
                if(abs(in[i]-out[i])&1)
                {
                    flag=false;break;
                }
            if(!flag)
            {
                printf("No euler circuit exist
    ");
            if(cas!=T)printf("
    ");
                continue;
            }
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                if(in[i]>out[i])
                {
                    solver.AddEdge(i,t,(in[i]-out[i])/2);
                }
                else if(out[i]>in[i])
                {
                    solver.AddEdge(s,i,(out[i]-in[i])/2);
                    sum+=abs(in[i]-out[i])/2;
                }
            }
    //        for(int i=0;i<solver.edges.size();i++)
    //        {
    //            printf("u==%d v==%d cap=%d
    ",solver.edges[i].from,solver.edges[i].to,solver.edges[i].cap);
    //        }
            if(sum!=solver.Maxflow(s,t,INF))
            {
                printf("No euler circuit exist
    ");
            if(cas!=T)printf("
    ");
                continue;
            }
            build();
            //for(int i=0;i<edges2.size();i++)
                //printf("from=%d to=%d
    ",edges2[i].from,edges2[i].to);
            while(!S.empty())S.pop();
            CL(vis,0);
            dfs(1);
            int first=0;
            while(!S.empty())
            {
                if(first)
                    printf(" ");
                first++;
                printf("%d",S.top());
                S.pop();
            }
            printf("
    ");
            if(cas!=T)printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    CSDN博客频道维护公告
    JavaScript高级编程II
    ORACLE触发器具体解释
    下拉刷新和上拉载入的原理
    在遍历中使用 iterator/reverse_iterator 进行 Erase 的使用方法
    python解析Yahoo的XML格式的天气预报,获取当天和近期几天的天气:
    CheckBoxPreference组件
    Java中Integer类的方法
    TFS(Team Foundation Server)介绍和入门
    电脑报2014年第43期 pdf高清版
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3147138.html
Copyright © 2020-2023  润新知