最小路径覆盖 = n - 最大匹配
1 #include <cstdio> 2 #include <string> 3 #include <vector> 4 #include <queue> 5 #include <cstring> 6 7 const int N = 200, INF = 0x3f3f3f3f; 8 9 int read() { 10 int x = 0, f = 1; 11 char c = getchar(); 12 while (!isdigit(c)) { 13 if (c == ‘-‘) f = -1; 14 c = getchar(); 15 } 16 while (isdigit(c)) { 17 x = (x << 3) + (x << 1) + (c ^ 48); 18 c = getchar(); 19 } 20 return x * f; 21 } 22 23 int n, m, matx[N], maty[N], dx[N], dy[N], dis, used[N]; 24 std::vector<int> G[N]; 25 26 bool bfs() { 27 std::queue<int> Q; dis = INF; 28 memset(dx, -1, sizeof dx); 29 memset(dy, -1, sizeof dy); 30 for (int i = 1; i <= n; ++ i) 31 if (matx[i] == 0) Q.push(i), dx[i] = 0; 32 while (!Q.empty()) { 33 int u = Q.front(); Q.pop(); 34 if (dx[u] > dis) break; 35 int size = G[u].size(); 36 for (int i = 0; i < size; ++ i) { 37 int v = G[u][i]; 38 if (dy[v] == -1) { 39 dy[v] = dx[u] + 1; 40 if (maty[v] == 0) dis = dy[v]; 41 else dx[maty[v]] = dy[v] + 1, Q.push(maty[v]); 42 } 43 } 44 } 45 return dis != INF; 46 } 47 48 bool dfs(int u) { 49 int size = G[u].size(); 50 for (int i = 0; i < size; ++ i) { 51 int v = G[u][i]; 52 if (!used[v] && dy[v] == dx[u] + 1) { 53 used[v] = 1; 54 if (maty[v] != 0 && dy[v] == dis) continue; 55 if (maty[v] == 0 || dfs(maty[v])) { 56 maty[v] = u, matx[u] = v; 57 return 1; 58 } 59 } 60 } 61 return 0; 62 } 63 64 int match() { 65 int res = 0; 66 while (bfs()) { 67 memset(used, 0, sizeof used); 68 for (int i = 1; i <= n; ++ i) { 69 if (matx[i] == 0 && dfs(i)) ++res; 70 } 71 } 72 return res; 73 } 74 75 int main() { 76 n = read(), m = read(); 77 for (int i = 1; i <= m; ++ i) { 78 int u = read(), v = read(); 79 G[u].push_back(v); 80 } 81 int tmp = match(); 82 for (int i = 1; i <= n; ++ i) { 83 int u = 0; 84 if (!maty[i]) u = i; 85 if (!u) continue; 86 while (u) { 87 printf("%d ", u); 88 u = matx[u]; 89 } puts(""); 90 } 91 printf("%d\n", n - tmp); 92 return 0; 93 }