题意:
求不相交的最小路径覆盖
思路:
连边跑二分图,匹配一条边相当于缩了一条边,答案为n-maxflow
如果是求可以相交的最小路径覆盖的话,先用Floyd跑出可达矩阵,然后所有可达的点连边跑二分图即可
代码:
这个dinic板子加边前要tot=1,否则每一对正反向流会乱掉
由于本题要输出方案,这里有两份代码,一份是跑最大流的时候记录流向,另一份是根据残余网络纪录流向
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <stack> #include <queue> #include <deque> #include <set> #include <vector> #include <ctime> #include <map> #define fst first #define sc second #define pb push_back #define mem(a, b) memset(a, b, sizeof(a)) #define lson l, mid, root << 1 #define rson mid + 1, r, root << 1 | 1 #define lc root << 1 #define rc root << 1 | 1 #define lowbit(x) ((x) & (-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PI; typedef pair<ll, ll> PLL; const db eps = 1e-6; const int mod = 1e9 + 7; const int maxn = 4e4 + 100; const int maxm = 4e5 + 100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); int head[maxn], d[maxn]; //层 int ver[maxm], edge[maxm], Next[maxm]; // edge[i]: c for edge_i int n, m, s, t, tot, maxflow; queue<int> q; int st[maxn]; void add(int x, int y, int z) { ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot; st[tot]=x; ver[++tot] = x, edge[tot] = 0, Next[tot] = head[y], head[y] = tot; st[tot]=y; } int du[maxn]; bool bfs() { mem(d, 0); while (!q.empty()) q.pop(); q.push(s); d[s] = 1; while (!q.empty()) { int x = q.front(); q.pop(); for (int i = head[x]; i; i = Next[i]) { if (edge[i] && !d[ver[i]]) { q.push(ver[i]); d[ver[i]] = d[x] + 1; if (ver[i] == t) return true; } } } return false; } int nx[maxn]; int dinic(int x, int flow) { if (x == t) return flow; int rest = flow, k; for (int i = head[x]; i; i = Next[i]) { if (edge[i] && d[ver[i]] == d[x] + 1) { k = dinic(ver[i], min(rest, edge[i])); if (!k) { d[ver[i]] = 0; } else { edge[i] -= k; edge[i ^ 1] += k; rest -= k; } } } return flow - rest; } int vis[maxn]; int pre[maxn]; int main() { mem(pre, -1); mem(nx,-1); s = 0; t = 1; tot = 1; scanf("%d %d", &n, &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%d %d", &x, &y); x *= 2; y *= 2; add(x, y + 1, 1); } for (int i = 1; i <= n; i++) { add(s, i * 2, 1); add(i * 2 + 1, t, 1); } int maxflow = 0; int flow; while (bfs()) { while (1) { flow = dinic(s, inf); if (flow == 0) break; maxflow += flow; } } for(int i = 2; i <= tot; i++){ if(edge[i]==0&&st[i]%2==0&&st[i]>=2&&st[i]<=2*n&&ver[i]!=s){ int x = st[i]/2; int y = (ver[i]-1)/2; //printf("%d %d ",x,y); pre[y] = x; nx[x] = y; } } for(int i = 1; i <= n; i++){ if(pre[i]==-1){ int x = i; while(x!=-1){ printf("%d ", x); x= nx[x]; } printf(" "); } } printf("%d ", n - maxflow); return 0; } /* 5 3 1 2 3 4 5 1 2 3 2 1 4 4 3 5 */
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <stack> #include <queue> #include <deque> #include <set> #include <vector> #include <ctime> #include <map> #define fst first #define sc second #define pb push_back #define mem(a, b) memset(a, b, sizeof(a)) #define lson l, mid, root << 1 #define rson mid + 1, r, root << 1 | 1 #define lc root << 1 #define rc root << 1 | 1 #define lowbit(x) ((x) & (-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PI; typedef pair<ll, ll> PLL; const db eps = 1e-6; const int mod = 1e9 + 7; const int maxn = 4e2 + 100; const int maxm = 4e5 + 100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); int head[maxn], d[maxn]; //层 int ver[maxm], edge[maxm], Next[maxm]; // edge[i]: c for edge_i int n, m, s, t, tot, maxflow; queue<int> q; void add(int x, int y, int z) { ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot; ver[++tot] = x, edge[tot] = 0, Next[tot] = head[y], head[y] = tot; } int du[maxn]; bool bfs() { mem(d, 0); while (!q.empty()) q.pop(); q.push(s); d[s] = 1; while (!q.empty()) { int x = q.front(); q.pop(); for (int i = head[x]; i; i = Next[i]) { if (edge[i] && !d[ver[i]]) { q.push(ver[i]); d[ver[i]] = d[x] + 1; if (ver[i] == t) return true; } } } return false; } int nx[maxn]; int dinic(int x, int flow) { if (x == t) return flow; int rest = flow, k; for (int i = head[x]; i; i = Next[i]) { if (edge[i] && d[ver[i]] == d[x] + 1) { k = dinic(ver[i], min(rest, edge[i])); if (!k) { d[ver[i]] = 0; } else { nx[x] = ver[i]; edge[i] -= k; edge[i ^ 1] += k; rest -= k; } } } return flow - rest; } int vis[maxn]; int pre[maxn]; int main() { mem(pre, -1); s = 404; t = 402; tot = 1; scanf("%d %d", &n, &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%d %d", &x, &y); x *= 2; y *= 2; add(x, y + 1, 1); } for (int i = 1; i <= n; i++) { add(s, i * 2, 1); add(i * 2 + 1, t, 1); } int maxflow = 0; int flow; while (bfs()) { while (1) { flow = dinic(s, inf); if (flow == 0) break; maxflow += flow; } } for (int i = 1; i <= n; i++) { pre[(nx[i * 2] - 1) / 2] = i; } for (int i = 1; i <= n; i++) { if (vis[i]) continue; if (pre[i] == -1) { int x = i; while (x) { vis[x] = 1; printf("%d ", x); x = (nx[x * 2] - 1) / 2; } printf(" "); } } printf("%d ", n - maxflow); return 0; } /* 5 3 1 2 3 4 5 1 2 3 2 1 4 4 3 5 */