loj6002「网络流 24 题」最小路径覆盖(最小不可相交路径覆盖+输出方案)

求有向无环图的最小不可相交路径覆盖。

把原图的每个点V拆成Vx和Vy两个点,如果有一条有向边A->B,那么就加边Ax−>By。这样就得到了一个二分图。那么最小路径覆盖=原图的结点数-新二分图的最大匹配数。

证明:一开始每个点都是独立的为一条路径,总共有n条不相交路径。我们每次在二分图里找一条匹配边就相当于把两条路径合成了一条路径,也就相当于路径数减少了1。所以找到了几条匹配边,路径数就减少了多少。所以有最小路径覆盖=原图的结点数-新二分图的最大匹配数。因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。

输出路径时,先找到路径起点,即没有bf的点,然后一直找他的匹配点gf输出。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 210
#define inf 0x3f3f3f3f
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-'0',ch=getchar();
    return x*f;
}
int n,m,h[N],num=0,bf[N],ans=0,gf[N];
bool f[N];
struct edge{
    int to,next;
}data[6010];
inline bool find(int x){
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(f[y]) continue;
        f[y]=1;if(!bf[y]||find(bf[y])){bf[y]=x;gf[x]=y;return 1;}
    }return 0;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();
    while(m--){
        int x=read(),y=read();
        data[++num].to=y;data[num].next=h[x];h[x]=num;
    }for(int i=1;i<=n;++i){
        memset(f,0,sizeof(f));if(find(i)) ans++;
    }
    for(int i=1;i<=n;++i){
        if(bf[i]) continue;
        int x=i;
        printf("%d",x);
        while(gf[x]){
            x=gf[x];
            printf(" %d",x);
        }
        puts("");
    }
    printf("%d\n",n-ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值