【网络流-最大流】飞行员配对方案问题

链接

https://www.luogu.org/problemnew/show/P2756

大意

给定一张图求其最大匹配

思路

由于数据的原因决定了这道题不能用匈牙利,所以就按照老师说的打了一个最大流

代码

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#define N 100001
using namespace std;
struct node{int to,next,v;}e[N];
int l[101],n,m,s,t,d[101],tot,f,ans,p;char c;
void add(int u,int v,int w){e[tot]={v,l[u],w};l[u]=tot++;return;}
void adds(int u,int v,int w){add(u,v,w);add(v,u,0);return;}
int read()//输入流
{
    f=0;p=1;
    while(c=getchar(),c<=47||c>=58) if(c=='-')p=-1;;f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
    return f*p;
}
void write(int x){if(x>9)write(x/10);putchar(x%10+48);return;}//输出流
void writes(int x){write(x);putchar(32);return;}
void writeln(int x){write(x);putchar(10);return;}
bool bfs()
{
    memset(d,-1,sizeof(d));
    queue<int>q;q.push(s);d[s]=0;//起点的时间戳为0
    while(q.size())
    {
        int x=q.front();q.pop();
        for(int i=l[x];i;i=e[i].next)
        {
            int y=e[i].to;
            if(e[i].v&&d[y]==-1)
            {
                d[y]=d[x]+1;//时间戳
                q.push(y);
                if(y==t) return true;//剪枝
            }
        }
    }
    return false;//无法到达汇点
}
int dfs(int x,int flow)//dinic
{
    int rest=0,k;
    if(x==t) return flow;//找到一个可行流
    for(int i=l[x];i;i=e[i].next)
    {
        int y=e[i].to;
        if(e[i].v&&d[y]-d[x]==1)//可以搜
        {
            k=dfs(y,min(e[i].v,flow-rest));//继续搜
            rest+=k;//表示已经流出的流量
            e[i].v-=k;
            e[i^1].v+=k;//逆向边
        }
    }
    if(!rest) d[x]=0;//没有可行边将其当做源点
    return rest;//返回
}
int main()
{
    n=read();m=read();//输入
    s=m+1;t=s+1;//源点和汇点
    for(int x=read(),y=read();x!=-1&&y!=-1;x=read(),y=read()) adds(x,y,1);//当x,y不为-1时输入
    for(int i=1;i<=n;i++) adds(s,i,1);//与源点建边
    for(int i=n+1;i<=m;i++) adds(i,t,1);//与汇点建边
    while(bfs()) ans+=dfs(s,1e9);//当可以搜救继续搜,不断找到可行流将它们的流出量的和算出来即为最大匹配量
    if(!ans) return printf("No Solution!")&0;//没有匹配
    writeln(ans);
    for(int i=0;i<tot;i+=2)
     if(e[i].to!=s&&e[i^1].to!=s&&e[i].to!=t&&e[i^1].to!=t)
      if(e[i^1].v)
       writes(e[i^1].to),writeln(e[i].to);//输出

}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/80743681