[luoguP2764] 最小路径覆盖问题(最大流 || 二分图最大匹配)

传送门

 

可惜洛谷上没有special judge,不然用匈牙利也可以过的,因为匈牙利在增广上有一个顺序问题,所以没有special judge就过不了了。

好在这个题的测试数据比较特殊,如果是网络流的话按照顺序加边,就可以过。

 

最小不相交路径覆盖 = 总点数 - 最大匹配数

 

——代码

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #define N 20001
  6 #define min(x, y) ((x) < (y) ? (x) : (y))
  7 #define max(x, y) ((x) > (y) ? (x) : (y))
  8 
  9 int n, m, cnt, sum, s, t;
 10 int head[N], belong[N], to[N], next[N], val[N], suc[N], cur[N], dis[N];
 11 
 12 inline int read()
 13 {
 14     int x = 0, f = 1;
 15     char ch = getchar();
 16     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
 17     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
 18     return x * f;
 19 }
 20 
 21 inline void add(int x, int y, int z)
 22 {
 23     to[cnt] = y;
 24     val[cnt] = z;
 25     next[cnt] = head[x];
 26     head[x] = cnt++;
 27 }
 28 
 29 inline bool bfs()
 30 {
 31     int i, u, v;
 32     std::queue <int> q;
 33     memset(dis, -1, sizeof(dis));
 34     q.push(s);
 35     dis[s] = 0;
 36     while(!q.empty())
 37     {
 38         u = q.front(), q.pop();
 39         for(i = head[u]; i ^ -1; i = next[i])
 40         {
 41             v = to[i];
 42             if(val[i] && dis[v] == -1)
 43             {
 44                 dis[v] = dis[u] + 1;
 45                 if(v == t) return 1;
 46                 q.push(v);
 47             }
 48         }
 49     }
 50     return 0;
 51 }
 52 
 53 inline int dfs(int u, int maxflow)
 54 {
 55     if(u == t) return maxflow;
 56     int i, v, d, ret = 0;
 57     for(i = cur[u]; i ^ -1; i = next[i])
 58     {
 59         v = to[i];
 60         if(val[i] && dis[v] == dis[u] + 1)
 61         {
 62             d = dfs(v, min(val[i], maxflow - ret));
 63             ret += d;
 64             cur[u] = i;
 65             val[i] -= d;
 66             val[i ^ 1] += d;
 67             if(d) suc[u] = v - n;
 68             if(ret == maxflow) return ret;
 69         }
 70     }
 71     return ret;
 72 }
 73 
 74 int main()
 75 {
 76     int i, j, x, y, now;
 77     n = read();
 78     m = read();
 79     s = 0, t = (n << 1) + 1;
 80     memset(head, -1, sizeof(head));
 81     for(i = 1; i <= m; i++)
 82     {
 83         x = read();
 84         y = read();
 85         add(x, y + n, 1);
 86         add(y + n, x, 0);
 87     }
 88     for(i = 1; i <= n; i++)
 89     {
 90         add(s, i, 1);
 91         add(i, s, 0);
 92         add(i + n, t, 1);
 93         add(t, i + n, 0);
 94     }
 95     while(bfs())
 96     {
 97         for(i = s; i <= t; i++) cur[i] = head[i];
 98         sum += dfs(s, 1e9);
 99     }
100     for(i = 1; i <= n; i++)
101         if(suc[i])
102         {
103             now = i;
104             while(now)
105             {
106                 printf("%d ", now);
107                 x = suc[now];
108                 suc[now] = 0;
109                 now = x;
110             }
111             puts("");
112         }
113     printf("%d\n", n - sum);
114     return 0;
115 }
View Code

 

posted @ 2017-06-01 20:03  zht467  阅读(135)  评论(0编辑  收藏  举报