【二分匹配】 [网络流24题] 最小路径覆盖问题

网络流24题中的经典题目。。。

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

const int maxn = 305;
const int maxm = 20005;

struct Edge
{
	int v;
	Edge *next;
}E[maxm], *H[maxn], *edges;
int res[maxn];
int vis[maxn];

void addedges(int u, int v)
{
	edges->v = v;
	edges->next = H[u];
	H[u] = edges++;
}

void init()
{
	edges = E;
	memset(H, 0, sizeof H);
	memset(res, -1, sizeof res);
}

bool find(int u)
{
	for(Edge *e = H[u]; e; e = e->next) if(!vis[e->v]) {
		int v = e->v;
		vis[v] = 1;
		if(res[v] == -1 || find(res[v])) {
			res[v] = u;
			return true;
		}
	}
	return false;
}

int n, m;
vector<int> ans;
int to[maxn];

void work()
{
	int u, v;
	for(int i = 1; i <= m; i++) {
		scanf("%d%d", &u, &v);
		addedges(u, v);
	}
	
	int result = 0;
	for(int i = 1; i <= n; i++) {
		memset(vis, 0, sizeof vis);
		if(find(i)) result++;
	}

	memset(to, 0, sizeof to);
	for(int i = 1; i <= n; i++) if(res[i] != -1) to[res[i]] = i;

	for(int i = 1; i <= n; i++) if(res[i] == -1) {
		ans.clear();
		int u = i;
		ans.push_back(u);
		while(to[u]) {
			u = to[u];
			ans.push_back(u);
		}
		for(int j = 0; j < ans.size(); j++) printf("%d%c", ans[j], j == ans.size() - 1 ? '\n' : ' ');
	}
	
	printf("%d\n", n - result);
}

int main()
{
	freopen("path3.in", "r", stdin);
	freopen("path3.out", "w", stdout);
	while(scanf("%d%d", &n, &m) != EOF) {
		init();
		work();
	}
	
	
	return 0;
}


你可能感兴趣的:(二分匹配)