网络流24题之T3——最小路径覆盖问题

来源:互联网 发布:vb和vb.net的区别 编辑:程序博客网 时间:2024/06/05 15:40
«问题描述:
给定有向图 G=(V,E)。设P G的一个简单路(顶点不相交)的集合。如果 V中每个
顶点恰好在
P 的一条路上,则称 P G的一个路径覆盖。P 中路径可以从 V 的任何一个顶
点开始,长度也是任意的,特别地,可以为
0G的最小路径覆盖是 G 的所含路径条数最少
的路径覆盖。
设计一个有效算法求一个有向无环图
G 的最小路径覆盖。
提示:设
V={12¼n},构造网络G1=(V1,E1)如下:
V1 ={x0, x1,,xn}È{y0, y1,,yn}
E1 ={(x0, xi) : iÎV}È{(yi, y0) : iÎV}È{(xi, yj ) : (i.j)Î E}
每条边的容量均为 1。求网络G1 的( x0, y0)最大流。
«编程任务:
对于给定的给定有向无环图 G,编程找出G 的一个最小路径覆盖。
«数据输入:
由文件 input.txt 提供输入数据。文件第 1 行有2 个正整数 nmn是给定有向无环图
G 的顶点数, mG 的边数。接下来的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
题解:这道题的模型就是题目名字--最小路径覆盖问题
我们把题目中所给的图中每个点拆成(xi,yi)两个点,对于一条路径(u,v)视为(xu,yv)这样的话等价于求二分图的最小路径覆盖。
我们在求解二分图的最大匹配时,需要将所有能拓展的路径拓展,剩下的是不能拓展的,也就是只能单点不成路径的,个数为n-最大匹配数,也就是答案
#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <memory.h>#include <math.h>#include <queue>#include <stack>#include <map>#include <vector>#include <limits.h>#include <malloc.h>#include <ctype.h>#include <float.h>using namespace std;const int oo=1000000005;const int Maxm=300005;const int Maxn=300005;int x,i,n,m,len,s,t,u,v;int head[Maxn];int dis[Maxn];int vis[Maxn];int cur[Maxn];struct edge{    int u,v,c,f,next;    edge(){        u=v=c=f=0;        next=-1;    }    edge(int x,int y,int z,int w,int t){        u=x;v=y;c=z;f=w;next=t;    }} e[Maxm];void add(int u,int v,int c,int f){    len++;    e[len]=edge(u,v,c,f,head[u]);    head[u]=len;}int bfs(){    queue <int> q;    for(i=1;i<=t;i++)        vis[i]=0;    q.push(s);    vis[s]=1;    dis[s]=1;    while(!q.empty()){        x=q.front();        q.pop();        for(i=head[x];i!=-1;i=e[i].next)            if(e[i].c>e[i].f&&!vis[e[i].v]){                dis[e[i].v]=dis[x]+1;                vis[e[i].v]=1;                q.push(e[i].v);            }    }    return vis[t];}int dfs(int x,int a){    if(x==t||a==0)        return a;    int f,flow=0;    int &i=cur[x];    for(;i!=-1;i=e[i].next)        if(dis[e[i].v]==dis[x]+1&&        (f=dfs(e[i].v,min(a,e[i].c-e[i].f)))){            e[i].f+=f;            a-=f;            flow+=f;            e[i^1].f-=f;            if(a==0)                break;        }    return flow;}int dinic(){    int flow=0;    while(bfs()){        for(i=1;i<=t;i++)            cur[i]=head[i];        flow+=dfs(s,oo);    }    return flow;}int main(){    freopen("test.in","r",stdin);    freopen("test.out","w",stdout);    scanf("%d %d",&n,&m);    for(i=1;i<=2*n+2;i++)        head[i]=-1;    len=-1;    s=2*n+1;    t=2*n+2;    for(i=1;i<=n;i++){        add(s,i,1,0);        add(i,s,0,0);        add(i+n,t,1,0);        add(t,i+n,0,0);    }    for(i=1;i<=m;i++){        scanf("%d %d",&u,&v);        add(u,v+n,1,0);        add(v+n,u,0,0);    }    printf("%d\n",n-dinic());    return 0;}


0 0