P2764 最小路径覆盖问题(最小路径覆盖+打印路径+匈牙利)
题目大意:求最小路径覆盖+打印可行解。
思路:二分图匹配问题,匈牙利就行,至于路径打印,
在匹配成功时多加一个nxt数组,标注和它匹配的是谁,
因为最小路径覆盖就是一条条线路,nxt和pre是一一对应的,
这样我们匹配结束后,去找那些没有pre的点,再nxt走到底,就是
一条路径。代码pre用的match代替
AC代码:
#include<bits/stdc++.h> #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 100005; const int inf = 0x3f3f3f3f; struct edge { int f, t, nxt; }e[maxn]; int hd[maxn], tot = 1; void add(int f, int t) { e[++tot] = { f,t,hd[f] }; hd[f] = tot; } bool vis[maxn]; int match[maxn], nxt[maxn]; int n, m; bool dfs(int u) { for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (vis[v])continue; vis[v] = 1; if (!match[v] || dfs(match[v])) { nxt[u] = v;//标记与其匹配的是 match[v] = u; return true; } } return false; } int main() { //freopen("test.txt", "r", stdin); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int a, b; scanf("%d%d", &a, &b); add(a, b); } for (int i = 1; i <= n; i++) { memset(vis, 0, sizeof(vis)); dfs(i); } int ans = 0; for (int i = 1; i <= n; i++) { if (!match[i]) {//没有前驱节点 ans++; printf("%d", i); int p = nxt[i]; while (p) { printf(" %d", p); p = nxt[p]; } printf("\n"); } } printf("%d\n", ans); return 0; }

浙公网安备 33010602011771号