【网络流】最小路径覆盖问题

最近在学网络流,老师叫我做这题,然后就A了。。

原题地址:https://www.luogu.org/problem/show?pid=2764

解题思路:网络流跑最大匹配,路径数就是节点数-匹配数。

附代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define mem(qaq,num) memset(qaq,num,sizeof(qaq));
#define ll long long
#define mod 1000000007
#define INF 2000000000
using namespace std;
struct zxy{
    int next,to,v;
}edge[2000001];
int n,cnt=1,head[8001],lev[8001],to[8001],que[8001],m;
bool b[4001];
inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void ins(int x,int y,int l){
    edge[++cnt].to=y,edge[cnt].next=head[x],edge[cnt].v=l,head[x]=cnt;
    edge[++cnt].to=x,edge[cnt].next=head[y],edge[cnt].v=0,head[y]=cnt;
}
inline bool bfs(int s,int e){
    mem(lev,-1);
    int t=1,h=0;
    que[0]=s;
    lev[s]=0;
    do{
        h++;
        int k=head[que[h]];
        while(k){
            if (lev[edge[k].to]==-1&&edge[k].v){
                lev[edge[k].to]=lev[que[h]]+1;
                que[++t]=edge[k].to;
            }
            k=edge[k].next;
        }
    }while(h<t);
    return lev[e]!=-1;
}
inline int dfs(int u,int v,int f){
    if (u==v) return f;
    int used=0,k=head[u];
    while(k){
        if (edge[k].v&&lev[edge[k].to]==lev[u]+1){
            int w=dfs(edge[k].to,v,min(edge[k].v,f-used));
            if (w){
                to[u]=edge[k].to;
                if (edge[k].to>n) b[edge[k].to-n]=1;
            }
            used+=w;
            edge[k].v-=w;
            edge[k^1].v+=w;
            if (used==f) return used;
        }
        k=edge[k].next;
    }
    return used;
}
int dinic(int s,int t){
    int flow=0;
    while(bfs(s,t))
        flow+=dfs(s,t,INF);
    return flow;
}
void read(){
    n=in(),m=in();
    int x,y;
    For(i,1,m) {
        x=in(),y=in();
        ins(x,y+n,INF);
    }
    For(i,1,n) ins(0,i,1),ins(i+n,(n<<1|1),1);
}
void solve(){
    int ans=n;
    ans-=dinic(0,2*n+1);
    For(i,1,n)
        if (b[i]) continue;
        else{
            printf("%d",i);
            int k=i;
            while(to[k]){
                k=to[k]-n;
                printf(" %d",k);
            }
            printf("
");
        }
    printf("%d",ans);
}
int main(){
    read();
    solve();
}

 本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

原文地址:https://www.cnblogs.com/Melacau/p/luogu2764.html