Luogu P2764 Minimum path coverage problem [maximum flow]

Topic link: https://www.luogu.org/problemnew/show/P2764

Topic description

"Problem Description:

Given a directed graph G=(V,E). Let P be a set of simple paths (disjoint vertices) of G. If every vertex in V is on exactly one path of P, then P is said to be a path cover of G. The path in P can start from any vertex of V, and the length is also arbitrary, in particular, it can be 0. The minimum path coverage of G is the path coverage of G that contains the fewest number of paths. Design an efficient algorithm to find the minimum path coverage of a directed acyclic graph G. Hint: Set V={1, 2, ...., n}, and construct the network G1=(V1, E1) as follows:

Each edge has a capacity of 1. Find the ( 0 x , 0 y ) maximum flow of network G1.

«Programming tasks:

For a given directed acyclic graph G, program to find a minimum path cover of G.

Input and output format

Input format:

The first line of the piece has 2 positive integers n and m. n is the number of vertices in a given directed acyclic graph G, and m is the number of edges in G. The next m lines, each with 2 positive integers i and j, represent a directed edge (i,j).

Output format:

From line 1, output one path per line. The last line of the file is the minimum number of paths.

Input and output example

Input example #1:
11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11
Sample output #1:
1 4 7 10 11
2 5 8
3 6 9
3

illustrate

1<=n<=150,1<=m<=6000

by @zhouyonglong SPJ

 

answer:

  Minimum path coverage problem. The answer is N-maximum binary matching (the proof is omitted, I feel that the hihoCoder is very detailed, it is recommended to read).

  Divide each point into two parts AB, and do maximum bisection matching. Then the source point to the point of part A is connected to the edge, and the edge weight is 1; the point of part B is connected to the sink point, the edge weight is 1, and the maximum flow is run...

  Regarding the path output problem, you can start from the sink to find the point where the residual capacity is 0 as the starting point to output the path recursively...

Code:

  1 #include <cstdio>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <queue>
  5 #include <cstring>
  6 using namespace std;
  7 const int N = 250*2+5;
  8 const int M = 6000*2+5;
  9 const int inf = 1e9;
 10 int n, m, S, T;
 11 int dep[N], cur[N];
 12 int head[N];
 13 struct Edge{
 14     int v, c, nex;
 15     Edge(int _v=0,int _c=0,int _nex=0):v(_v),c(_c),nex(_nex){}
 16 }E[M];
 17 
 18 int cnt;
 19 void add(int u, int v, int c){
 20     E[cnt].v = v;
 21     E[cnt].c = c;
 22     E[cnt].nex = head[u];
 23     head[u] = cnt++;
 24 }
 25 
 26 bool bfs() {
 27     queue<int> q;
 28     memset(dep, -1, sizeof(dep));
 29     q.push(S); dep[S] = 0;
 30     while(!q.empty()) {
 31         int u = q.front(); q.pop();
 32         for(int i = head[u]; ~i; i = E[i].nex) {
 33             int v = E[i].v;
 34             if(E[i].c && dep[v] == -1) {
 35                 dep[v] = dep[u] + 1;
 36                 q.push(v);
 37             }
 38         }
 39     }
 40     return dep[T] != -1;
 41 }
 42 int dfs(int u, int flow) {
 43     if(u == T) return flow;
 44     int w, used=0;
 45     for(int i = head[u]; ~i; i = E[i].nex) {
 46         int v = E[i].v;
 47         if(dep[v] == dep[u] + 1) {
 48             w = flow - used;
 49             w = dfs(v, min(w, E[i].c));
 50             E[i].c -= w;  E[i^1].c += w;
 51             if(v) cur[u] = i;
 52             used += w;
 53             if(used == flow) return flow;
 54         }
 55     }
 56     if(!used) dep[u] = -1;
 57     return used;
 58 }
 59 int dinic() {
 60     int ans = 0;
 61     while(bfs()) {
 62         for(int i = 0; i <= T;i++)
 63             cur[i] = head[i];
 64         ans += dfs(S, inf);
 65     }
 66     return ans;
 67 }
 68 void print(int x, int &f) {
 69     if(x <= S) return;
 70     if(f == 1) f = 0;
 71     else printf(" ");
 72     printf("%d", x);
 73 
 74     for(int i = head[x]; ~i; i = E[i].nex) {
 75         if(!E[i].c){
 76             print(E[i].v - n, f);
 77         }
 78     }
 79 }
 80 int main() {
 81     int i, j, u, v;
 82     scanf("%d%d", &n, &m);
 83     memset(head, -1, sizeof(head));
 84     cnt = 0;
 85     S = 0; T = 2*n+1;
 86     vector<int>g[N];
 87     for(i = 0; i <= n; ++i) g[i].clear();
 88     for(i = 0; i < m; ++i) {
 89         scanf("%d%d", &u, &v);
 90         add(u, v+n, 1); add(v+n, u, 0);
 91     }
 92     for(i = 1; i <= n; ++i) add(S,i,1),add(i,S,0);
 93     for(i = 1; i <= n; ++i) add(i+n,T,1),add(T,i+n,0);
 94     
 95     int ans = dinic();
 96     
 97     for(i = head[T]; ~i; i = E[i].nex) {
 98         if(!E[i].c) {
 99             int f = 1;
100             print(E[i].v - n, f);
101             puts("");
102         }
103     }
104     printf("%d\n", n-ans);
105     return 0;
106 }
107 
108 /*
109 7 7
110 1 2
111 1 3
112 2 4
113 3 4
114 4 5
115 4 6
116 5 7
117 */
View Code

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326845966&siteId=291194637