• 【PowerOJ1738】最小路径覆盖


    给定有向图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 行开始,每行输出 一条路径。文件的最后一行是最少路径数。
    Sample Input
    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
    Sample Output
    1 4 7 10 11 2 5 8 3 6 9 3
     
    题解:
    每一个点拆成i和i+n两个,每一个表示他在边中是前驱还是后继,然后所有的前驱init(S,i,1)所有的后继(i+n,T,1)
    每一条边(u,v)改成u的前驱到v的后继有一条(u,v+n,INF)的边
    然后答案为n-最大流
    然后输出路径,已知路径的开始一定后继没有被访问过,所以i+n到T的边依旧为1,可以找出所有路径的开始节点。
    然后就是判断他和哪些边匹配过,不断递归输出.
    细节很巧妙,详情看代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=1005,M=200005,INF=1999999999;
     7 int gi(){
     8     int str=0;char ch=getchar();
     9     while(ch>'9' || ch<'0')ch=getchar();
    10     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
    11     return str;
    12 }
    13 int n,m,num=1,head[N],S=0,T,d[N];
    14 struct Lin{
    15     int next,to,dis;
    16 }a[M];
    17 void init(int x,int y,int z){
    18     a[++num].next=head[x];
    19     a[num].to=y;
    20     a[num].dis=z;
    21     head[x]=num;
    22     a[++num].next=head[y];
    23     a[num].to=x;
    24     a[num].dis=0;
    25     head[y]=num;
    26 }
    27 int q[N],dep[N];
    28 bool bfs()
    29 {
    30     memset(dep,0,sizeof(dep));
    31     q[1]=S;dep[S]=1;
    32     int x,u,t=0,sum=1;
    33     while(t!=sum)
    34     {
    35         x=q[++t];
    36         for(int i=head[x];i;i=a[i].next){
    37             u=a[i].to;
    38             if(dep[u] || a[i].dis<=0)continue;
    39             dep[u]=dep[x]+1;q[++sum]=u;
    40         }
    41     }
    42     return dep[T];
    43 }
    44 int dfs(int x,int flow)
    45 {
    46     if(T==x || !flow)return flow;
    47     int u,tmp,tot=0;
    48     for(int i=head[x];i;i=a[i].next){
    49         u=a[i].to;
    50         if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue;
    51         tmp=dfs(u,min(a[i].dis,flow));
    52         tot+=tmp;flow-=tmp;
    53         a[i].dis-=tmp;a[i^1].dis+=tmp;
    54         if(!flow)break;
    55     }
    56     return tot;
    57 }
    58 int maxflow()
    59 {
    60     int tmp,tot=0;
    61     while(bfs()){
    62         tmp=dfs(S,INF);
    63         while(tmp)tot+=tmp,tmp=dfs(S,INF);
    64     }
    65     return tot;
    66 }
    67 void hfs(){
    68     int u;
    69     for(int i=head[T];i;i=a[i].next){
    70         if(!a[i].dis)d[a[i].to]=true;
    71     }
    72 }
    73 void Print(int x)
    74 {
    75     printf("%d ",x);
    76     for(int i=head[x];i;i=a[i].next){
    77         if(a[i].to!=S && a[i].dis==INF-1)Print(a[i].to-n);
    78     }
    79 }
    80 int main()
    81 {
    82     int x,y;
    83     n=gi();m=gi();
    84     T=2*n+1;
    85     for(int i=1;i<=n;i++)init(S,i,1),init(i+n,T,1);
    86     for(int i=1;i<=m;i++){
    87         x=gi();y=gi();
    88         init(x,y+n,INF);
    89     }
    90     int tp=maxflow();
    91     hfs();
    92     for(int i=1;i<=n;i++){
    93         if(!d[i+n])continue;
    94         Print(i);
    95         printf("
    ");
    96     }
    97     printf("%d",n-tp);
    98 }
  • 相关阅读:
    基于windows server 2016和sqlserver 2016 AlwaysOn的群集配置
    Mysql基于Mysql Cluster+MysqlRouter的集群部署方案
    阿里云ECS部署Redis主备哨兵集群遇到的问题
    Informix数据库配置与连接
    Linux系统中Redis和Tomcat的PID文件路径设置
    Linux端口映射,80端口映射到8080端口
    Tomcat优化配置
    Tomcat配置自定义JAVA环境
    VMware虚拟机系统无法使用桥接联网
    PostgreSQL远程访问设置
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6867115.html
Copyright © 2020-2023  润新知