zoukankan      html  css  js  c++  java
  • [网络流24题] 最小路径覆盖问题

    问题描述:

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

    提示:

    设V={1,2,...  ,n},构造网络G1=(V1,E1)如下:


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

    编程任务:

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

    数据输入:

      由文件input.txt提供输入数据。文件第1行有2个正整数n和m。n是给定有向无环图G的顶点数,m是G的边数。接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。

    结果输出:

      程序运行结束时,将最小路径覆盖输出到文件output.txt中。从第1行开始,每行输出一条路径。文件的最后一行是最少路径数。

    题解:

      最小路径覆盖,建图方法:把所有点分别加入二分图中的x集和y集,如果i节点可以连向j,就让在x集中的i连向一条在y集的j,权值为inf。然后让S连向x集,权值为1。让y集连向T,权值为1。跑网络流,路径的个数就是点的总数减去最大流的值。 证明理解

      统计方案也很好理解,正如''证明理解'',里的那样,如果x集里的u流了容量为一的边到y集里的v,则说明v表示的点在DAG中是u表示的点的后继,那么他们两个在同一个路径覆盖上,用并查集把他们联系起来,最后统计一下就成了。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 using namespace std;
     10 const int inf=1e9;
     11 const int maxn=1000,maxm=120000;
     12 int N,M,S,T,ANS;
     13 struct Edge{
     14     int to,rest,next;
     15 }e[150000];
     16 int head[maxn],cnt=1;
     17 inline void Addedge(int x,int y,int z){
     18     e[++cnt].to=y; e[cnt].rest=z; e[cnt].next=head[x]; head[x]=cnt;
     19     e[++cnt].to=x; e[cnt].rest=0; e[cnt].next=head[y]; head[y]=cnt;
     20 }
     21 int dis[maxn];
     22 inline bool BFS(){
     23     memset(dis,0,sizeof(dis));
     24     static queue<int> Q;
     25     while(!Q.empty()) Q.pop();
     26     Q.push(S); dis[S]=1;
     27     while(!Q.empty()){
     28         int x=Q.front(); Q.pop();
     29         for(int i=head[x];i;i=e[i].next){
     30             int y=e[i].to;
     31             if(dis[y]==0&&e[i].rest!=0){
     32                 dis[y]=dis[x]+1;
     33                 Q.push(y);
     34             }
     35         }
     36     }
     37     if(dis[T]) return true;
     38     return false;
     39 }
     40 inline int DFS(int x,int flow){
     41     if(x==T) return flow;
     42     int tmp,now=0;
     43     for(int i=head[x];i;i=e[i].next){
     44         int y=e[i].to;
     45         if(dis[y]==dis[x]+1&&e[i].rest!=0){
     46             tmp=DFS(y,min(flow-now,e[i].rest));
     47             e[i].rest-=tmp;
     48             e[i^1].rest+=tmp;
     49             now+=tmp;
     50             if(now==flow) return now;
     51         }
     52     }
     53     if(!now) dis[x]=0;
     54     return now;
     55 }
     56 inline void dinic(){
     57     while(BFS()) ANS-=DFS(S,inf);
     58 }
     59 
     60 int fa[maxn];
     61 inline int find(int x){
     62     if(x!=fa[x]) fa[x]=find(fa[x]);
     63     return fa[x];
     64 }
     65 int main(){
     66     //freopen("path3.in","r",stdin);
     67     //freopen("path3.out","w",stdout);
     68     scanf("%d%d",&N,&M); 
     69     ANS=N; S=0; T=N*2+1;
     70     for(int i=1,u,v;i<=M;i++){
     71         scanf("%d%d",&u,&v);
     72         Addedge(u,v+N,inf);
     73     }
     74     for(int i=1;i<=N;i++){
     75         Addedge(S,i,1);
     76         Addedge(i+N,T,1);
     77     }
     78     dinic();
     79     for(int i=1;i<=N;i++) fa[i]=i;
     80     for(int i=1;i<=N;i++){
     81         for(int j=head[i];j;j=e[j].next){
     82             int y=e[j].to;
     83             if(e[j].rest==inf-1){
     84                 int u=i,v=y-N;
     85                 int fau=find(u),fav=find(v);
     86                 if(fau!=fav){
     87                     if(fau<fav) fa[fav]=fau;
     88                     else fa[fau]=fav;
     89                 }
     90             }
     91         }
     92     }
     93     for(int i=1;i<=N;i++){
     94         if(fa[i]==i){
     95             printf("%d ",i);
     96             for(int j=1;j<=N;j++){
     97                 if(j!=i&&fa[j]==i) printf("%d ",j);
     98             }
     99             printf("
    ");
    100         }
    101     }
    102     printf("%d
    ",ANS);
    103     return 0;
    104 }
  • 相关阅读:
    在线古书式竖排工具
    智能实验室-全能优化(Guardio) 5.04.0.1040
    智能实验室-全能优化(Guardio) 5.03.0.1011
    在线专用链双向转换
    智能实验室-杀马(Defendio) 4.32.0.1020
    智能实验室-杀马(Defendio) 4.31.0.1010
    智能实验室-全能优化(Guardio) 4.999.0.981
    智能实验室-杀马(Defendio) 4.27.0.951
    智能实验室-全能优化(Guardio) 5.02.0.1000
    智能实验室-结构化存储浏览器(SSExplorer) 2.0.0.200
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5199951.html
Copyright © 2011-2022 走看看