Cogs 728. [网络流24题] 最小路径覆盖问题

  1. [网络流24题] 最小路径覆盖问题
    ★★☆ 输入文件:path3.in 输出文件:path3.out 评测插件
    时间限制:1 s 内存限制:128 MB
    算法实现题8-3 最小路径覆盖问题(习题8-13)
    ´问题描述:
    给定有向图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行开始,每行输出
    一条路径。文件的最后一行是最少路径数。
    输入文件示例
    input.txt
    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
    输出文件示例
    output.txt
    1 4 7 10 11
    2 5 8
    3 6 9
    3
    数据范围:
    1<=n<=150,1<=m<=6000
/*
最小路径覆盖数=V-最大流.
然后拆点建图.
搞一个超级源点和汇点跑dinic.
输出的时候在残余网络里找贡献边.
恩就是这样. 
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define MAXN 10001
using namespace std;
struct data{int v,next,c;}e[MAXN*4];
int n,m,max1=1e9,ans,tot,cut=1,dis[MAXN*2],head[MAXN*2],next[MAXN*2];
bool in[MAXN*2];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x*f;
}
void add(int u,int v,int x)
{
    e[++cut].v=v;
    e[cut].c=x;
    e[cut].next=head[u];
    head[u]=cut;
}
bool bfs()
{
    memset(dis,-1,sizeof dis);
    queue<int>q;
    q.push(0);
    dis[0]=0;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]==-1&&e[i].c)
            {
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
    }
    return dis[n*2+1]!=-1;
}
int dfs(int u,int y)
{
    if(u==n*2+1) return y;
    int rest=0;
    for(int i=head[u];i&&rest<y;i=e[i].next)
    {
        int v=e[i].v;
        if(dis[v]==dis[u]+1&&e[i].c)
        {
            int x=dfs(v,min(e[i].c,y-rest));
            rest+=x;
            e[i].c-=x;
            e[i^1].c+=x;
        }
    }
    if(!rest) dis[u]=-1;
    return rest;
}
void print()
{
    for(int u=1;u<=n;u++)
      for(int i=head[u];i;i=e[i].next)
      {
          int v=e[i].v;
          if(e[i].c==max1-1) in[v-n]=true,next[u]=v-n;
      }
    for(int i=1;i<=n;i++)
    {
        int x=i;
        if(!in[x])
        {
            while(x) printf("%d ",x),x=next[x];
            printf("\n");
        }
    }
}
void dinic(int s,int t)
{
    while(bfs()) ans+=dfs(s,max1);
    print();
    printf("%d\n",n-ans);
    return ;
}
int main()
{
    freopen("path3.in","r",stdin);
    freopen("path3.out","w",stdout); 
    int x,y;
    n=read(),m=read();
    for(int i=1;i<=n;i++) add(0,i,1),add(i,0,0);
    for(int i=1;i<=n;i++) add(i+n,n*2+1,1),add(2*n+1,i+n,0);
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read();
        add(x,y+n,max1),add(y+n,x,0);
    }
    dinic(0,n*2+1);
    return 0;
}
posted @ 2017-01-14 18:11  nancheng58  阅读(135)  评论(0编辑  收藏  举报