zoukankan      html  css  js  c++  java
  • P2764 最小路径覆盖问题

    题目描述

    «问题描述:

    给定有向图G=(V,E)。设P 是G 的一个简单路(顶点不相交)的集合。如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖。P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图G 的最小路径覆盖。提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下:

    每条边的容量均为1。求网络G1的( 0 x , 0 y )最大流。

    «编程任务:

    对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。

    输入输出格式

    输入格式:

    件第1 行有2个正整数n和m。n是给定有向无环图G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。

    输出格式:

    从第1 行开始,每行输出一条路径。文件的最后一行是最少路径数。

    输入输出样例

    输入样例#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
    输出样例#1: 复制
    1 4 7 10 11
    2 5 8
    3 6 9
    3


    这题是一个网络流常用模型,
    最小路径覆盖问题;
    这题反向思考,就是点的数目-最大的二分匹配;
    就是最少的路径数目;
    这题算出最小路径,直接套网络流模板就行了;
    但是要输出路径这就很恶心了;
    我放弃了我自己原来的网络流模板;
    找了一个更加适合输出路径的代码;
    输出路径真心恶心

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 #define inf 0x3fffffff
      7 using namespace std;
      8 const int maxn = 1e5 + 10;
      9 int head[maxn], sign, cur[maxn];
     10 int s, t, d[maxn];
     11 struct node {
     12     int to, w, next;
     13 } edge[maxn] ;
     14 void creat() {
     15     memset(head, -1, sizeof(head));
     16     sign = 0;
     17 }
     18 void add(int u, int v, int w) {
     19     edge[sign].to = v;
     20     edge[sign].w = w;
     21     edge[sign].next = head[u];
     22     head[u] = sign++;
     23     edge[sign].to = u;
     24     edge[sign].w = 0;
     25     edge[sign].next = head[v];
     26     head[v] = sign++;
     27 }
     28 int bfs() {
     29     queue<int>q;
     30     memset(d, 0, sizeof(d));
     31     d[s] = 1;
     32     q.push(s);
     33     while(!q.empty()) {
     34         int top = q.front();
     35         q.pop();
     36         for (int i = head[top] ; ~i  ; i = edge[i].next ) {
     37             int to = edge[i].to;
     38             if (edge[i].w > 0 && d[to] == 0)  {
     39                 d[to] = d[top] + 1;
     40                 if (to == t) return 1;
     41                 q.push(to);
     42             }
     43         }
     44     }
     45     return d[t] != 0;
     46 }
     47 int dfs(int top, int flow ) {
     48     if (top == t) return flow;
     49     int ans = 0, x = 0;
     50     for (int i = cur[top] ; ~i ; i = edge[i].next)  {
     51         int to = edge[i].to;
     52         if (edge[i].w > 0 && d[to] == d[top] + 1) {
     53             x = dfs(to, min(flow - ans, edge[i].w)) ;
     54             edge[i].w -= x;
     55             edge[i ^ 1].w += x;
     56             if (edge[i].w) cur[top] = i;
     57             ans += x;
     58             if (ans == flow) return flow;
     59         }
     60     }
     61     if (ans == 0) return d[top] = 0;
     62     return ans;
     63 }
     64 
     65 int dinic(int n) {
     66     int ans = 0;
     67     while(bfs()) {
     68         for (int i = 0 ; i <= n ; i++)
     69             cur[i] = head[i];
     70         ans += dfs(s, inf);
     71     }
     72     return ans;
     73 }
     74 int n, m, vis[maxn];
     75 void go(int x, int &f) {
     76     int loc = x + n;
     77     vis[x] = 1;
     78     for (int i = head[loc] ; ~i ; i = edge[i].next)
     79         if (edge[i].w == 1  && edge[i].to != n * 2 + 1) go(edge[i].to, f) ;
     80     if (f == 1) f = 0;
     81     printf(" ");
     82     printf("%d", x);
     83 }
     84 int main() {
     85     scanf("%d%d", &n, &m);
     86     creat();
     87     s = 0, t = 2 * n + 1;
     88     for (int i = 1 ; i <= n ; i++)
     89         add(s, i, 1), add(i + n, t, 1);
     90     int x, y;
     91     while(m--) {
     92         scanf("%d%d", &x, &y);
     93         add(x, y + n, 1);
     94     }
     95     int ans = n - dinic(t);
     96     for (int i = head[t]; ~i ; i = edge[i].next) {
     97         if (edge[i].w == 1 && !vis[edge[i].to - n]) {
     98             int f = 1;
     99             go(edge[i].to - n, f);
    100             printf("
    ");
    101         }
    102     }
    103     printf("%d
    ", ans);
    104     return 0;
    105 }


  • 相关阅读:
    字符串反转,
    留意 这两个 name,
    fileurlwithpath,
    原来是 临时的那张图片没有删除,code 516
    下载图片,
    Codevs 5564 陶陶摘苹果2
    黑科技--用处自己探索
    Codevs 1299 切水果 水一发
    COdevs 天梯 水题系列
    COdevs 2823 锁妖塔
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/8994175.html
Copyright © 2011-2022 走看看