网络流解决混合欧拉回路问题
网络流解决混合欧拉回路问题
解析
例题
欧拉回路,只不过图即存在有向边,又存在无向边,问是否存在欧拉回路
n点, m边的图,下面m条边。标准图论输入
下面代码中的路径第三个值为‘1’表示有向边,否则是双向边。
代码
#include <bits/stdc++.h>
using namespace std;
struct Dinic {
static const int MAXN = 1050 + 7;
static const int MAXM = MAXN * MAXN;
static const int INF = 0x3f3f3f3f;
int n, m, s, t;
int first[MAXN], cur[MAXN], dist[MAXN], sign;
struct Node {
int to, flow, next;
} edge[MAXM * 4];
inline void init(int start, int vertex, int ss, int tt) {
n = vertex, s = ss, t = tt;
for(int i = start; i <= n; i++ ) {
first[i] = -1;
}
sign = 0;
}
inline void add_edge(int u, int v, int flow) {
edge[sign].to = v, edge[sign].flow = flow, edge[sign].next = first[u];
first[u] = sign++;
edge[sign].to = u, edge[sign].flow = 0, edge[sign].next = first[v];
first[v] = sign++;
}
inline int dinic() {
int max_flow = 0;
while(bfs(s, t)) {
for(int i = 0; i <= n; i++ ) {
cur[i] = first[i];
}
max_flow += dfs(s, INF);
}
return max_flow;
}
bool bfs(int s, int t) {
memset(dist, -1, sizeof(dist));
queue<int>que;
que.push(s), dist[s] = 0;
while(!que.empty()) {
int now = que.front();
que.pop();
if(now == t) {
return 1;
}
for(int i = first[now]; ~i; i = edge[i].next) {
int to = edge[i].to, flow = edge[i].flow;
if(dist[to] == -1 && flow > 0) {
dist[to] = dist[now] + 1;
que.push(to);
}
}
}
return 0;
}
int dfs(int now, int max_flow) {
if(now == t) {
return max_flow;
}
int ans = 0, next_flow = 0;
for(int &i = cur[now]; ~i; i = edge[i].next) {
int to = edge[i].to, flow = edge[i].flow;
if(dist[to] == dist[now] + 1 && flow > 0) {
next_flow = dfs(to, min(max_flow - ans, flow));
ans += next_flow;
edge[i].flow -= next_flow;
edge[i ^ 1].flow += next_flow;
if(ans == max_flow) {
return max_flow;
}
}
}
if(ans == 0) {
return dist[now] = 0;
}
return ans;
}
} dinic;
const int MAXN = 1050;
int n, m;
int indeg[MAXN], outdeg[MAXN];
struct Input {
int u, v, d;
} edge[MAXN];
int main()
{
while(~scanf("%d %d", &n, &m)) {
memset(indeg, 0, sizeof(indeg));
memset(outdeg, 0, sizeof(outdeg));
dinic.init(0, n + 1, 0, n + 1);
for(int i = 1; i <= m; i++ ) {
scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].d);
indeg[ edge[i].v ]++;
outdeg[ edge[i].u ]++;
if(edge[i].d == 0) {
dinic.add_edge(edge[i].u, edge[i].v, 1);
dinic.add_edge(edge[i].v, edge[i].u, 1);
}
}
bool ok = 1;
int sum = 0;
for(int i = 1; i <= n; i++) {
int delta = abs(indeg[i] - outdeg[i]);
if(delta % 2 == 1) {
ok = 0;
break;
}
if(indeg[i] > outdeg[i]) {
dinic.add_edge(0, i, delta / 2);
sum += delta / 2;
} else {
dinic.add_edge(i, n + 1, delta / 2);
}
}
if(!ok) {
puts("impossible");
continue;
}
if(dinic.dinic() == sum) {
puts("possible");
} else {
puts("impossible");
}
}
return 0;
}