• 【最大流,二分图匹配】【hdu2063】【过山车】


    题意:裸的求二分图匹配


    建立一个源点 连向一边所有的点 容量为1;

    另外一边点都连向汇点  容量为1;

    二分图的边容量也为1

    源点汇点求一遍最大流即可


    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    using namespace std;
    const int MAXN=2000+5;
    const int MAXM=10000+5;
    const int INF=0x3f3f3f3f;
    struct Edge
    {
        int to,next,cap,flow;
        void get(int a,int b,int c,int d)
        {
            to=a;next=b;cap=c;flow=d;
        }
    }edge[MAXM];
    int tol;
    int head[MAXN];
    int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
    void init()
    {
        tol=0;
        memset(head,-1,sizeof(head));
    }
    //单向图三个参数,无向图四个参数
    void addedge(int u,int v,int w,int rw=0)
    {
        edge[tol].get(v,head[u],w,0);head[u]=tol++;
        edge[tol].get(u,head[v],rw,0);head[v]=tol++;
    }
    int sap(int start,int end,int N)
    {
        memset(gap,0,sizeof(gap));
        memset(dep,0,sizeof(dep));
        memcpy(cur,head,sizeof(head));
        int u=start;
        pre[u]=-1;
        gap[0]=N;
        int ans=0;
        while(dep[start]<N)
        {
            if(u==end)
            {
                int Min=INF;
                for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                    if(Min>edge[i].cap-edge[i].flow)
                       Min=edge[i].cap-edge[i].flow;
                for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                {
                    edge[i].flow+=Min;
                    edge[i^1].flow-=Min;
                }
                u = start;
                ans+=Min;
                continue;
            }
            bool flag=false;
            int v;
            for(int i=cur[u];i !=-1;i=edge[i].next)
            {
                v=edge[i].to;
                if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
                {
                    flag=true;
                    cur[u]=pre[v]=i;
                    break;
                }
            }
            if(flag)
            {
                u=v;
                continue;
            }
            int Min=N;
            for(int i=head[u];i!=-1;i=edge[i].next)
                if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
            gap[dep[u]]--;
            if(!gap[dep[u]]) return ans;
            dep[u]=Min+1;
            gap[dep[u]]++;
            if(u!=start) u=edge[pre[u]^1].to;
        }
        return ans;
    }
    int KK,MM,NN;
    void input()
    {
        int a,b;
        for(int i=1;i<=KK;i++)
        {
            scanf("%d%d",&a,&b);
            addedge(a,b+MM,1);
        }
    
    }
    void solve()
    {
        int ANS;
        for(int i=1;i<=MM;i++)
        {
            addedge(MM+NN+1,i,1);
        }
        for(int i=MM+1;i<=MM+NN;i++)
        {
            addedge(i,MM+NN+2,1);
        }
        ANS=sap(MM+NN+1,MM+NN+2,MM+NN+2);
        printf("%d
    ",ANS);
    }
    void File()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    }
    int main()
    {
      //  File();
        while(cin>>KK>>MM>>NN&&KK)
        {
            init();
            input();
            solve();
        }
    }
    


  • 相关阅读:
    单表查询
    阻塞非阻塞同步异步&异步回调
    基于协程的TCP并发编程
    协程
    死锁与递归锁
    线程池和进程池
    GIL全局解释器锁
    数据库——多表关系
    常用数据类型与约束
    Python基础(目录)
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480387.html
Copyright © 2020-2023  润新知