ssl 2601 网络流24题1 飞行员配对方案问题

题目

n个外籍飞行员和m个皇家飞行员分别能互相配合,给出能互相配合的飞行员序号对,每个飞行员只能配一次对,求最大对数

题解

最大匹配也可以做,但是练习网络流才是第一要务。。。
建图很简单,设源点s和汇点t,在每个外籍飞行员和s之间连边,每个皇家飞行员和t之间连边,然后跑最大流就可以了,这里用的是dinic
我改了许久,wa,te,re都试过,最后发现,数组开小了!!!

代码

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;

struct edge{
    int y,c,ne;
}e[10000];
int n,m,ls[105],s,t,cnt,cur[105],dis[105],a[105][105];
queue<int> que;

void addedge(int u,int v,int c)
{ 
    a[u][v]=1;
    e[++cnt].y=v;e[cnt].c=c;e[cnt].ne=ls[u];ls[u]=cnt;
    e[++cnt].y=u;e[cnt].c=0;e[cnt].ne=ls[v];ls[v]=cnt;
}

bool bfs()
{
    for (int i=0;i<=n+1;i++) dis[i]=0;
    while (!que.empty()) que.pop();
    dis[s]=1;que.push(s);
    while (!que.empty())
    {
        int u=que.front();que.pop();
        for (int i=ls[u];i;i=e[i].ne)
        if (e[i].c&&!dis[e[i].y])
        {
            dis[e[i].y]=dis[u]+1;
            if (e[i].y==t) return(true);
            que.push(e[i].y);
        }
    }
    return(false);
}

int dfs(int x,int maxf)
{
    if (x==t||!maxf) return(maxf);
    int ret=0;
    for (int &i=cur[x];i;i=e[i].ne)
    if (e[i].c&&(dis[x]+1==dis[e[i].y]))
    {
        int f=dfs(e[i].y,min(e[i].c,maxf-ret));
        e[i].c-=f;
        e[i^1].c+=f;
        ret+=f; 
        if (maxf==ret) break;
    }
    return(ret);
}

int dinic(int t)
{
    int ans=0;
    s=0;
    while (bfs())
    {
        for (int i=0;i<=n+1;i++) cur[i]=ls[i];
        ans+=dfs(s,1000000000);
    }
    return(ans);
}

void init()
{
    int i,j;
    cnt=1;
    for (int i=1;i<=m;i++)
    {
        addedge(0,i,1);
        a[0][i]=1;
    }
    for (int i=m+1;i<=n;i++)
    {
        addedge(i,n+1,1);
        a[i][n+1]=1;
    }
    scanf("%d%d",&i,&j);
    while ((i!=-1)&&(j!=-1))
    {
        if (!a[i][j]) addedge(i,j,1);
        scanf("%d%d",&i,&j);
    }
}

int main()
{
    scanf("%d%d",&m,&n);

    init();

    s=0;t=n+1;
    printf("%d",dinic(t));
}

猜你喜欢

转载自blog.csdn.net/yjy_aii/article/details/80183437
今日推荐