P2764 最小路径覆盖问题

传送门:

二分图构图思想!!!

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
#define ll long long
#define re register
#define pb push_back;
const int N=1e4;
const int inf=1e9;
inline void read(int &a)
{
    a=0;
    int d=1;
    char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
queue <int> q;
struct note
{
    int next,dis,v,u;
}edge[4*N];
int head[2*N],f[2*N],num,deep[2*N],n,m;
inline void init()
{
    for(re int i=1;i<=n;i++)
        f[i]=i;
    memset(head,0xff,sizeof(head));
    num=-1;
}
inline void add(int u,int v,int dis)
{
    edge[++num].next=head[u];
    edge[num].v=v;
    edge[num].u=u;
    edge[num].dis=dis;
    head[u]=num;
}
inline bool bfs(int s,int t)
{
    while(!q.empty())
        q.pop();
    memset(deep,0x7f,sizeof(deep));
    deep[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(re int i=head[now];i!=-1;i=edge[i].next)
        {
            if(deep[edge[i].v]>inf&&edge[i].dis)
            {
                deep[edge[i].v]=deep[now]+1;
                q.push(edge[i].v);
            }
        }
    }
    if(deep[t]<inf)
        return true;
    return false;
}
inline int dfs(int now,int t,int limit)
{
    if(now==t||!limit)
        return limit;
    int flow=0,x;
    for(re int i=head[now];i!=-1;i=edge[i].next)
    {
        if(deep[now]+1==deep[edge[i].v]&&(x=dfs(edge[i].v,t,min(edge[i].dis,limit))))
        {
            flow+=x;
            edge[i].dis-=x;
            edge[i^1].dis+=x;
            limit-=x;
            if(!limit)
                break;
        }
    }
    return flow;
}
inline int dinic(int s,int t)
{
    int ans=0;
    while(bfs(s,t))
        ans+=dfs(s,t,inf);
    return ans;
}
inline void write(int x)
{
    printf("%d ",x);
    for(re int i=head[x];i!=-1;i=edge[i].next)
        if(!edge[i].dis&&edge[i].v>n)
            write(edge[i].v-n);
}
inline int getv(int v){return f[v]=v==f[v]?v:getv(f[v]);}
int main()
{
    //freopen("in.txt","r",stdin);
    read(n);
    read(m);
    init();
    int s=0,t=(n<<1)+1;
    for(re int i=0;i<m;i++)
    {
        int x,y;
        read(x);
        read(y);
        add(x,n+y,1);
        add(n+y,x,0);
    }
    for(re int i=1;i<=n;i++)
        add(s,i,1),add(i,s,0);
    for(re int i=n+1;i<=(n<<1);i++)
        add(i,t,1),add(t,i,0);
    int ans=n-dinic(s,t);
    for(re int i=0;i<=num;i++)
        if(edge[i].u>=1&&edge[i].u<=n&&edge[i].v>n&&edge[i].v<t&&!edge[i].dis)
            f[getv(edge[i].v-n)]=getv(edge[i].u);
    for(re int i=1;i<=n;i++)
        if(f[i]==i)
            write(i),putchar('
');
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/acm1ruoji/p/11107122.html