码迷,mamicode.com
首页 > 其他好文 > 详细

UVa10735 Euler Circuit (混合图的欧拉回路,最大流)

时间:2016-09-25 17:16:30      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

链接:http://vjudge.net/problem/UVA-10735

分析:题目保证底图联通,所以连通性就不用判断了。其次,不能把无向边转成有向边来做,因为本题中无向边只能经过一次,而拆成两条有向边之后变成了“沿着两个相反方向各经过一次”,所以本题不能拆边,而只能给边定向。首先我们给无向边任意定向,比如无向边(u,v),可以将其定向为u->v,于是u的出度和v的入度多1(在保证出入度相等的前提下,后者等价于出度少1),那我们这样随意定向以后反悔了怎么办呢?比如最后u的出度为4,入度为2,因此我们需要有将刚刚任意定向的边反向的机会,我们可以把出度看成是“物品”,先前任意定向的结果把这个“物品”交给了u,最后可能u多了这个“物品”,而和u通过刚才任意定向的边相连的结点v正好需要这个“物品”,所以我们在网络流建图时加上边(u,v,1)表示u能提供1个出度给v,相当于反悔了开始的决定将边反向了,然后哪些点需要扔掉一些出度呢?答案是out(i)>in(i),哪些点需要一些出度呢?答案是out(i)<in(i),将源点S向要扔掉出度的结点连一条容量为(out[i]-in[i])/2的弧,从需要出度的结点向汇点连一条容量为(in[i]-out[i])/2的弧,当且仅当源点连出去的弧全部满载整个图的所有结点出入度相等。(注意:in(i)和out(i)奇偶性不同则问题无解)。

 

  1 #include <cstdio>
  2 #include <vector>
  3 #include <cstring>
  4 #include <queue>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 100 + 5;
  9 const int INF = 1000000000;
 10 
 11 struct Edge {
 12     int from, to, cap, flow;
 13     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
 14 };
 15 
 16 struct EdmondsKarp {
 17     int n, m;
 18     vector<Edge> edges;
 19     vector<int> G[maxn];
 20     int a[maxn];
 21     int p[maxn];
 22 
 23     void init(int n) {
 24         for (int i = 0; i < n; i++) G[i].clear();
 25         edges.clear();
 26     }
 27 
 28     void AddEdge(int from, int to, int cap) {
 29         edges.push_back(Edge(from, to, cap, 0));
 30         edges.push_back(Edge(to, from, 0, 0));
 31         m = edges.size();
 32         G[from].push_back(m - 2);
 33         G[to].push_back(m - 1);
 34     }
 35 
 36     int Maxflow(int s, int t) {
 37         int flow = 0;
 38         for (;;) {
 39             memset(a, 0, sizeof(a));
 40             queue<int> Q;
 41             Q.push(s);
 42             a[s] = INF;
 43             while (!Q.empty()) {
 44                 int x = Q.front(); Q.pop();
 45                 for (int i = 0; i < G[x].size(); i++) {
 46                     Edge& e = edges[G[x][i]];
 47                     if (!a[e.to] && e.cap > e.flow) {
 48                         p[e.to] = G[x][i];
 49                         a[e.to] = min(a[x], e.cap - e.flow);
 50                         Q.push(e.to);
 51                     }
 52                 }
 53                 if (a[t]) break;
 54             }
 55             if (!a[t]) break;
 56             for (int u = t; u != s; u = edges[p[u]].from) {
 57                 edges[p[u]].flow += a[t];
 58                 edges[p[u] ^ 1].flow -= a[t];
 59             }
 60             flow += a[t];
 61         }
 62         return flow;
 63     }
 64 };
 65 
 66 EdmondsKarp g;
 67 
 68 const int maxm = 500 + 5;
 69 
 70 int n, m, u[maxm], v[maxm], directed[maxm], id[maxm], diff[maxn];
 71 
 72 vector<int> G[maxn];
 73 vector<int> vis[maxn];
 74 vector<int> path;
 75 
 76 void euler(int u) {
 77     for (int i = 0; i < G[u].size(); i++)
 78         if (!vis[u][i]) {
 79             vis[u][i] = 1;
 80             euler(G[u][i]);
 81             path.push_back(G[u][i] + 1);
 82         }
 83 }
 84 
 85 void print_answer() {
 86     for (int i = 0; i < n; i++) { G[i].clear(); vis[i].clear(); }
 87     for (int i = 0; i < m; i++) {
 88         bool rev = false;
 89         if (!directed[i] && g.edges[id[i]].flow > 0) rev = true;
 90         if (!rev) { G[u[i]].push_back(v[i]); vis[u[i]].push_back(0); }
 91         else { G[v[i]].push_back(u[i]); vis[v[i]].push_back(0); }
 92     }
 93 
 94     path.clear();
 95     euler(0);
 96 
 97     printf("1");
 98     for (int i = path.size()-1; i >= 0; i--) printf(" %d", path[i]);
 99     printf("\n");
100 }
101 
102 int main() {
103     int T;
104     scanf("%d", &T);
105     while (T--) {
106         scanf("%d%d", &n, &m);
107         g.init(n + 2);
108         memset(diff, 0, sizeof(diff));
109         for (int i = 0; i < m; i++) {
110             scanf("%d%d", &u[i], &v[i]);
111             u[i]--; v[i]--;
112             diff[u[i]]++; diff[v[i]]--;
113             char dir; while ((dir = getchar()) ==  );
114             directed[i] = (dir == D ? 1 : 0);
115             if (dir == U) { id[i] = g.edges.size(); g.AddEdge(u[i], v[i], 1); }
116         }
117         bool ok = true;
118         int s = n, t = n + 1, sum = 0;
119         for (int i = 0; i < n; i++) {
120             if (diff[i] % 2 != 0) { ok = false; break; }
121             if (diff[i] > 0) { g.AddEdge(s, i, diff[i] / 2); sum += diff[i] / 2; }
122             if (diff[i] < 0) { g.AddEdge(i, t, -diff[i] / 2); }
123         }
124         if (!ok || sum != g.Maxflow(s, t)) { printf("No euler circuit exist\n"); }
125         else print_answer();
126         if (T) putchar(\n);
127     }
128     return 0;
129 }

 

UVa10735 Euler Circuit (混合图的欧拉回路,最大流)

标签:

原文地址:http://www.cnblogs.com/XieWeida/p/5906202.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!