uva10735

计算每一个节点的入度出度,然后判断每个节点的入度出度之差是否为偶数

如果不是则不存在欧拉回路,反之则有可能通过改变无向边的方向从而使得图中存在欧拉回路

怎么变呢,如果一个点的入度大于出度,那么我们必然需要将该点所连接的无向边改变方向,然而改变之后又会影响到其他的结点,

注意这个影响的过程,我们可以将这种影响的过程看做度数的转移,比如结点1和2之间有一条无向边,我最初给这条边指定了一个方向,比如1指向2

当我们改变这个方向时,1的出度减少1,入度增加1,而2的出度增加1,入度减少1,

回顾这个过程,结点1的最初的状态是需要一个入度,而2可以给1提供一个入度,所以可以看做节点2向节点1转移了一个货物

当然这样做的条件是,1需要,2有,也就是对于某一个结点来说它的入度比出度大2,那么他就是需要一个出度,反之可以提供一个入度

然后我们依照这个标准建图求一个最大流就行了,当然必须要添加2个源点

关于欧拉回路的打印,百度吧,或者直接参考刘汝佳代码即可

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<assert.h>
#include<ctime>
#include<vector>
#include<list>
#include<map>
#include<set>
#include<sstream>
#include<stack>
#include<queue>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define me(s)  memset(s,0,sizeof(s))
#define pf printf
#define sf scanf
#define Di(x) int x;scanf("%d",&x)
#define in(x) inp(x)
#define in2(x,y) inp(x),inp(y)
#define in3(x,y,z) inp(x),inp(y),inp(z)
#define ins(x) scanf("%s",x)
#define ind(x) scanf("%lf",&x)
#define IO ios_base::sync_with_stdio(0);cin.tie(0)
#define READ freopen("C:/Users/ASUS/Desktop/in.txt","r",stdin)
#define WRITE freopen("C:/Users/ASUS/Desktop/out.txt","w",stdout)
template<class T> void inp(T &x) {//读入优化
    char c = getchar(); x = 0;
    for (; (c < 48 || c>57); c = getchar());
    for (; c > 47 && c < 58; c = getchar()) { x = (x << 1) + (x << 3) + c - 48; }
}
typedef pair <int, int> pii;
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
const double eps = 1e-15;

const int maxn=100+5;
struct Edge{
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} 
};
struct EdmondsKarp{
    int n,m;
    vector<Edge> edges; 
    vector<int>G[maxn];//邻接表,G[i][j]表示节点i的第j条边在edges数组中的需要
    int a[maxn];//当起点到i的可改进量
    int p[maxn];//最短路树上p的入弧编号
    void init(int 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));//反向弧
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    int Maxflow(int s,int t){
        int flow=0;
        for(;;){
            //开始寻找增广路
            memset(a,0,sizeof(a));
            queue<int> Q;
            Q.push(s);
            a[s]=inf;
            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(!a[e.to]&&e.cap>e.flow){
                        p[e.to]=G[x][i];
                        a[e.to]=min(a[x],e.cap-e.flow);
                        Q.push(e.to);
                    }
                }
                if(a[t]) break;//找到了一条增广路
            }
            if(!a[t]) break;//不存在增广路,当前流就是最大流
            for(int u=t;u!=s;u=edges[p[u]].from){
                edges[p[u]].flow+=a[t];
                edges[p[u]^1].flow-=a[t];
            }
            flow+=a[t];
        }
        return flow;
    }
};
EdmondsKarp g;
const int maxm=500+5; //edges size
int u[maxm],v[maxm],diff[maxm],id[maxm],directed[maxm];
int n,m;
vector<int> G[maxn];
vector<int> vis[maxn];
vector<int> path;

void euler(int u) {
    for(int i = 0; i < G[u].size(); i++)
        if(!vis[u][i]) {
            vis[u][i] = 1;
            euler(G[u][i]);
            path.push_back(G[u][i]+1);
        }
}

void print_answer() {
    for(int i = 0; i < n; i++) {
        G[i].clear();
        vis[i].clear();
    }
    for(int i = 0; i < m; i++) {
        bool rev = false;
        if(!directed[i] && g.edges[id[i]].flow > 0)
            rev = true;
        if(!rev) {
            G[u[i]].push_back(v[i]);
            vis[u[i]].push_back(0);
        } else {
            G[v[i]].push_back(u[i]);
            vis[v[i]].push_back(0);
        }
    }

    path.clear();
    euler(0);

    printf("1");
    for(int i = path.size()-1; i >= 0; i--)
        printf(" %d", path[i]);
    printf("\n");
}

int main(){
    //READ;
    //WRITE;
    Di(T);
    while(T--){
        in2(n,m);
        g.init(n+2);
        me(diff);
        for(int i=0;i<m;i++){
            char s[5];
            scanf("%d%d%s",&u[i],&v[i],s);
            u[i]--;v[i]--;
            directed[i]=(s[0]=='D'?1:0);
            diff[u[i]]++;
            diff[v[i]]--;
            if(!directed[i]){
                id[i] = g.edges.size();
                g.AddEdge(u[i],v[i],1);
            }
        }
        bool ok=true;
        for(int i=0;i<n;i++)
        if(diff[i]%2) {
            ok=false;
            break;
        }
         int s = n, t = n+1;
        if(ok) {
            int sum = 0;
            for(int i = 0; i < n; i++) {
                if(diff[i] > 0) {
                    g.AddEdge(s, i, diff[i]/2);    // provide "out-degree"
                    sum += diff[i]/2;
                }
                if(diff[i] < 0) {
                    g.AddEdge(i, t, -diff[i]/2);
                }
            }
            if(g.Maxflow(s, t) != sum)
                ok = false;
        }

        if(!ok)  pf("No euler circuit exist\n");
        else print_answer();
        if(T) puts("");
    }
}

猜你喜欢

转载自www.cnblogs.com/033000-/p/10060685.html