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<=n<=150,1<=m<=6000

    由@FlierKing提供SPJ

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 #define INF 0x3f3f3f3f
     10 const int maxn = 6e4+10;
     11 int n,m,s,t,u,v;
     12 struct Edge { 
     13     int from, to, cap, flow;
     14 };
     15 vector<Edge> edges;
     16 vector<int> G[maxn];
     17 bool vis[maxn];
     18 int d[maxn], cur[maxn],nxt[maxn];
     19 
     20 void Init()
     21 {
     22     memset(d,0,sizeof d);
     23     for(int i=0;i<=2*n+1;i++) G[i].clear();
     24 }
     25 
     26 void AddEdge(int from, int to, int cap) 
     27 {
     28     edges.push_back((Edge){from, to, cap, 0});
     29     edges.push_back((Edge){to, from, 0, 0});
     30     int m = edges.size();
     31     G[from].push_back(m-2); G[to].push_back(m-1);
     32 }
     33 
     34 bool bfs() 
     35 {
     36     memset(vis,0,sizeof vis);
     37     queue<int> q;
     38     q.push(s);
     39     d[s] = 0; vis[s] = 1;
     40     while (!q.empty()) 
     41     {
     42         int x = q.front(); q.pop();
     43         for(int i = 0; i < G[x].size(); ++i) 
     44         {
     45             Edge &e = edges[G[x][i]];
     46             if (!vis[e.to] && e.cap > e.flow) 
     47             {
     48                 vis[e.to] = 1;
     49                 d[e.to] = d[x] + 1;
     50                 q.push(e.to);
     51             }
     52         }
     53     }
     54     return vis[t];
     55 }
     56 
     57 int dfs(int x,int a) 
     58 {
     59     if(x == t || a == 0) return a;
     60     int flow = 0, f;
     61     for(int &i = cur[x]; i < G[x].size(); ++i) 
     62     {
     63         Edge &e = edges[G[x][i]];
     64         if (d[e.to] == d[x] + 1 && (f=dfs(e.to, min(a, e.cap-e.flow))) > 0) 
     65         {
     66             e.flow += f;
     67             edges[G[x][i]^1].flow -= f;
     68             flow += f; a -= f;
     69             if (a == 0) break;
     70         }
     71     }
     72     return flow;
     73 }
     74 
     75 int MaxFlow(int s, int t) 
     76 {
     77     int flow = 0;
     78     while (bfs()) 
     79     {
     80         memset(cur,0,sizeof cur);
     81         flow += dfs(s, INF);
     82     }
     83     return flow;
     84 }
     85 
     86 int main()
     87 {
     88     while(scanf("%d%d",&n,&m)!=EOF)
     89     {
     90         Init();
     91         for(int i=1;i<=m;i++)
     92         {
     93             scanf("%d%d",&u,&v);
     94             AddEdge(u,v+n,1);     
     95         }
     96         s=0,t=2*n+1;
     97         for(int i=1;i<=n;i++)
     98         {
     99             AddEdge(s,i,1);
    100             AddEdge(i+n,t,1);
    101         }
    102         int ans=MaxFlow(s,t);
    103         memset(nxt,0,sizeof nxt);
    104         memset(vis,0,sizeof vis);
    105         
    106         for(int i=1;i<=n;i++)
    107         {
    108             for(int j=0;j<G[i].size();j++)
    109             {
    110                 Edge &e=edges[G[i][j]];
    111                 if(e.flow>0) nxt[e.from]=e.to-n;
    112             }
    113         }
    114         for(int i=1;i<=n;i++)
    115         {
    116             if(!vis[i])
    117             {
    118                 int a=i;
    119                 vis[a]=1;
    120                 printf("%d",a);
    121                 while(nxt[a])
    122                 {
    123                     a=nxt[a];
    124                     vis[a]=1;
    125                     printf(" %d",a);
    126                 }
    127                 printf("
    ");
    128             }
    129         }
    130         printf("%d
    ",n-ans);
    131     }
    132     return 0;    
    133 }  
    View Code

      

  • 相关阅读:
    仪器的接口类型
    FIREDAC用于LINUX报头文件FireDAC.VCLUI.Wait找不到
    咏南中间件网站框架
    UNIGUI下载文件
    UNIGUI上传文件
    unigui回车代替TAB
    DELPHI开发LINUX桌面程序
    TDiocpCoderTcpServer 使用
    UNIGUI换版本注意事项
    git 撤销提交的文件
  • 原文地址:https://www.cnblogs.com/csushl/p/9526588.html
Copyright © 2011-2022 走看看