【网络流24题 #03】最小路径覆盖问题

题目链接:最小路径覆盖问题

 

哇 卡在输出也是醉了

 

重要结论:最小路径覆盖数 = 结点数(拆成边之前) -  最大流

 

本题也是点拆边

与【网络流24题 #04】魔术球问题 

有异曲同工之妙

 

void output(int x){
    if(x >= S) return ;
    printf("%d ", x >> 1);
    for(int i = head[x]; i != -1; i = edge[i].next)
        if(!edge[i].w && edge[i].v < S) output(edge[i].v - 1);
}   

……


 for(int i = 1; i <= n; i++) fa[i] = i;
    for(int i = 0; i <= esize; i += 2) {
        if(!edge[i].w && edge[i].v < S && edge[i].u < S){
            fa[find(edge[i].v >> 1)] = find(edge[i].u >> 1);        
        }
    }
    for(int i = 1; i <= n; i++){
        if(find(i) == i){
            output(i << 1);
            printf("\n");
        }

内心戏:(╯‵□′)╯︵┻━┻

悄咪咪:居然还打扰H神吃饭…

 

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <queue>
  4 #include <cstring>
  5 #include <cmath>
  6 using namespace std;
  7 const int N = 4e4 + 5;
  8 const int inf = 0x3f3f3f3f;
  9 int n, m;
 10 struct Edge{
 11     int u, v, w, next;
 12 }edge[N << 1];
 13 int head[N], esize = -1;
 14 bool vis[N];
 15 int next[N], fa[N];
 16 inline void addedge(int x, int y, int z){
 17     edge[++esize] = (Edge){x, y, z, head[x]};
 18     head[x] = esize;
 19     edge[++esize] = (Edge){y, x, 0, head[y]};
 20     head[y] = esize;
 21 }
 22 queue<int> q;
 23 int dep[N];
 24 int S, T;
 25 
 26 bool bfs(){
 27     int fro;
 28     q.push(S); 
 29     memset(dep, 0, sizeof(dep));
 30     dep[S] = 1;
 31     while(!q.empty()){
 32         fro = q.front(); q.pop();
 33         for(int i = head[fro]; i != -1; i = edge[i].next){
 34             int vv = edge[i].v;
 35             if(!dep[vv] && edge[i].w > 0){
 36                 dep[vv] = dep[fro] + 1;
 37                 q.push(vv);
 38             }
 39         }
 40     }
 41     return dep[T];
 42 }
 43 
 44 int dfs(int x, int rest){
 45     if(x == T || !rest) return rest;
 46     for(int i = head[x], vv, ww, d; i != -1; i = edge[i].next){
 47         vv = edge[i].v, ww = edge[i].w;
 48         if(dep[vv] != dep[x] + 1) continue;
 49         d = dfs(vv, min(rest, ww));
 50         if(d > 0){
 51             edge[i].w -= d;
 52             edge[i ^ 1].w += d;
 53             return d;
 54         }
 55     }
 56     return 0;
 57 }
 58 
 59 int dinic(){
 60     int ret = 0;
 61     while(bfs()){
 62         ret += dfs(S, inf);
 63     }
 64     return ret;
 65 }
 66 
 67 int find(int x){
 68     return x == fa[x] ? x : fa[x] = find(fa[x]);
 69 }
 70 
 71 void output(int x){
 72     if(x >= S) return ;
 73     printf("%d ", x >> 1);
 74     for(int i = head[x]; i != -1; i = edge[i].next)
 75         if(!edge[i].w && edge[i].v < S) output(edge[i].v - 1);
 76 }
 77 
 78 int main(){
 79     scanf("%d%d", &n, &m);
 80     memset(head, -1, sizeof(head));
 81     memset(next, -1, sizeof(next));
 82     S = N - 3, T = N - 2;
 83     for(int i = 1; i <= n; i++){
 84         addedge(S, i << 1, 1);
 85         addedge(i << 1 | 1, T, 1);
 86     }
 87     for(int i = 1, x, y; i <= m; i++){
 88         addedge(x << 1, y << 1 | 1, 1);
 89     }
 90     int cnt = n - dinic();
 91     for(int i = 1; i <= n; i++) fa[i] = i;
 92     for(int i = 0; i <= esize; i += 2) {
 93         if(!edge[i].w && edge[i].v < S && edge[i].u < S){
 94             fa[find(edge[i].v >> 1)] = find(edge[i].u >> 1);
 95         }
 96     }
 97     for(int i = 1; i <= n; i++){
 98         if(find(i) == i){
 99             output(i << 1);
100             printf("\n");
101         }
102     }
103     printf("%d", cnt);
104     return 0;
105 }
Whole

 

 

posted @ 2018-07-07 20:44  hjmmm  阅读(166)  评论(0编辑  收藏  举报