【dinic最小割 输出割边】J - Sabotage UVA - 10480

https://vjudge.net/contest/68128#problem/J

/// 跑完最大流后的残余网络
/// 从源点及汇点开始 分别标记能到达的点
/// 遍历边 两端点标记不同即为割边
/// (源点不能到达的点必与汇点连通 标记源点能到达的点)
/// (遍历边 一端标记 一端未标记为割边)

#include <bits/stdc++.h>
using namespace std;

const long long inf = 1e18;
const int mn = 100, mm = 1500;

int ST[mm], ED[mm];
bool biao[mn][mn];
bool vis[mn];

int edge;
int fr[mn];
int lv[mn];
struct node
{
	int to, nx, fan;
	long long val;
} e[mm];

long long flow = 0;
void init()
{
	flow = 0;
	edge = 0;
	memset(fr, -1, sizeof fr);
	memset(vis, 0, sizeof vis);
	memset(biao, 0, sizeof biao);
}

void addedge(int u, int v, long long w)
{
	edge++;
	e[edge].to = v, e[edge].val = w, e[edge].nx = fr[u], e[edge].fan = edge + 1;
	fr[u] = edge;
	edge++;
	e[edge].to = u, e[edge].val = w, e[edge].nx = fr[v], e[edge].fan = edge - 1;
	fr[v] = edge;
}

void bfs(int s)
{
	memset(lv, 0, sizeof lv);
	lv[s] = 1;
	queue<int> q;
	q.push(s);
	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		for (int i = fr[t]; i != -1; i = e[i].nx)
		{
			if (e[i].val > 0 && !lv[e[i].to])
			{
				lv[e[i].to] = lv[t] + 1;
				q.push(e[i].to);
			}
		}
	}
}

long long dfs(int s, int t, long long f)
{
	if (s == t)
		return f;
	for (int i = fr[s]; i != -1; i = e[i].nx)
	{
		if (e[i].val > 0 && lv[s] < lv[e[i].to])
		{
			long long d = dfs(e[i].to, t, min(f, e[i].val));
			if (d > 0)
			{
				e[i].val -= d;
				e[e[i].fan].val += d;
				return d;
			}
		}
	}
	return 0;
}

void max_flow(int s, int t)
{
	while (1)
	{
		bfs(s);
		if (!lv[t])
			break;

		long long f = 0;
		while ((f = dfs(s, t, inf)) > 0)
			flow += f;
	}
}

void bfs2(int s)
{
	queue<int> q;
	q.push(s);
    vis[s] = 1;
	while (!q.empty())
	{
		int u = q.front();
		q.pop();
		for (int i = fr[u]; i != -1; i = e[i].nx)
		{
			int v = e[i].to;
			if (e[i].val > 0 && !vis[v])
			{
				vis[v] = 1;
				q.push(v);
			}
		}
	}
}

int main()
{
	//freopen("D:\\in.txt", "r", stdin);
	int n, m;
	while (~scanf("%d %d", &n, &m) && (n || m))
	{
		init();

		int st = 1, ed = 2;

		for (int i = 1; i <= m; i++)
		{
			int a, b;
			long long c;
			scanf("%d %d %lld", &a, &b, &c);
			ST[i] = a, ED[i] = b;
			addedge(a, b, c);
		}

		max_flow(st, ed);

		bfs2(st); /// 从源点开始bfs
		for (int i = 1; i <= m; i++)
		{
			if ((vis[ST[i]] && !vis[ED[i]]) || (!vis[ST[i]] && vis[ED[i]]))
			{
				if (!biao[ST[i]][ED[i]]) // 去重
				{
					biao[ST[i]][ED[i]] = biao[ED[i]][ST[i]] = 1;
                    printf("%d %d\n", ST[i], ED[i]);
				}
			}
		}

		printf("\n");
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/ummmmm/article/details/81356927