UVA-10735 - Euler Circuit(混合欧拉回路输出)

题意:给你一个图,有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 \n",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\n",u,v);
        if(!vis[mm])
        {
            //printf("u=%d v=%d\n",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\n");
        if(cas!=T)printf("\n");
            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\n",solver.edges[i].from,solver.edges[i].to,solver.edges[i].cap);
//        }
        if(sum!=solver.Maxflow(s,t,INF))
        {
            printf("No euler circuit exist\n");
        if(cas!=T)printf("\n");
            continue;
        }
        build();
        //for(int i=0;i<edges2.size();i++)
            //printf("from=%d to=%d\n",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("\n");
        if(cas!=T)printf("\n");
    }
    return 0;
}

 

posted @ 2013-06-20 21:07  z.arbitrary  阅读(471)  评论(0编辑  收藏  举报