最小路径覆盖问题 最小路径覆盖+输出解

来源:互联网 发布:java填空题 编辑:程序博客网 时间:2024/04/27 17:10

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

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

第1 行有2个正整数n和m。n是给定有向无环图
G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。

将最小路径覆盖输出。从第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 4 7 10 11
2 5 8
3 6 9
3

题目可以在这里提交:http://wikioi.com/homework/23/


没有SPJ就是蛋疼。。。


分析:最小路径覆盖,至于输出解,直接循着匹配边找就行。


代码:

//复杂度:O(n*e)#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll;   //记得必要的时候改成无符号const int maxn=40005;   //点数const int maxm=40005;   //边数struct EdgeNode{    int to;    int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y){    edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt++;}int n,m,v[maxn],pre[maxn],pip[maxn];void init(){    cnt=1;    memset(head,-1,sizeof(head));}bool dfs(int x){    int y;    for(int i=head[x];i!=-1;i=edge[i].next)    {        y=edge[i].to;        if(!v[y])        {            v[y]=1;            if(!pre[y]||dfs(pre[y]))            {                pre[y]=x;                pip[x]=y;                return true;            }        }    }    return false;}int erfenpipei(){    int sum=0;    memset(pre,0,sizeof(pre));    memset(pip,0,sizeof(pip));    for(int i=1;i<=n;i++)    {        memset(v,0,sizeof(v));        if(dfs(i))            sum++;    }    return sum;}int chu[maxn],a[maxn];int main(){    int i,j,x,y,ans,ret,js;    while(~scanf("%d%d",&n,&m))    {        init();        for(i=1;i<=m;i++){            scanf("%d%d",&x,&y);            add(x,y);        }        ans=erfenpipei();        memset(v,0,sizeof(v));        for(i=1;i<=n;i++){            if(!v[i]){                ret=js=0;                chu[ret++]=i;                int t=i; v[t]=1;                while(pre[t]!=0){                    t=pre[t];                    v[t]=1;                    chu[ret++]=t;                }                for(j=ret-1;j>=0;j--)a[js++]=chu[j];                t=i;                while(pip[t]!=0){                    t=pip[t];                    v[t]=1;                    a[js++]=t;                }                for(j=0;j<js;j++){                    if(j==0)printf("%d",a[j]);                    else printf(" %d",a[j]);                }                printf("\n");            }        }        printf("%d\n",n-ans);    }    return 0;}



0 0
原创粉丝点击