• P3386 【模板】二分图匹配


    题目描述

    给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数

    题目地址


    匈牙利算法

    • 本质上是对于每个点进行dfs,并在递归的同时不断找出新的增广路.
    • 注意点:
    1. 需要使用vis数组并在每次dfs前清空,防止死循环.
    2. 模板里不需要加双向边.
    3. vis并不是增广成功才能设置,失败不设置一定会爆栈的.
    4. 在dfs的过程中累加ans会导致增广路全部被计入.

    Dinic算法

    • 和其他题一样,对面的点集需要序号平移n个单位.

    匈牙利算法

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int MAXN=10010,MAXM=1000010;
    struct Edge{
    	int from,to,nxt;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v){
    	e[++edgeCnt].from=u;
    	e[edgeCnt].to=v;
    	e[edgeCnt].nxt=head[u];
    	head[u]=edgeCnt;
    }
    int vis[MAXN],match[MAXN];
    int dfs(int x){
    	for(int i=head[x];i;i=e[i].nxt){
    		int nowV=e[i].to;
    		if(vis[nowV])continue;
    		vis[nowV]=1;
    		if(!match[nowV]||dfs(match[nowV])){
    			match[nowV]=x;
    			return 1;
    		}
    	}
    	return 0;
    }
    int main(){
    	int n,m,e;
    	scanf("%d%d%d",&n,&m,&e);
    	for(int i=1;i<=e;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		if(v>m||u>n)continue;
    		addEdge(u,v);
    	}
    	int ans=0;
    	for(int i=1;i<=n;i++){
    		memset(vis,0,sizeof(vis));
    		if(dfs(i))ans++;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }

    Dinic算法

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int MAXN=1000010,MAXM=1000010;
    int s,t;
    struct Edge{
        int from,to,w,nxt;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v,int w){
        e[++edgeCnt].from=u;
        e[edgeCnt].to=v;
        e[edgeCnt].w=w;
        e[edgeCnt].nxt=head[u];
        head[u]=edgeCnt;
    }
    int d[MAXN];
    bool bfs(){
        memset(d,0,sizeof(d));
        queue<int> q;
        d[s]=1;q.push(s);
        while(!q.empty()){
            int nowV=q.front();q.pop();
            for(int i=head[nowV];i;i=e[i].nxt){
                int nowNode=e[i].to;
                if(!d[nowNode]&&e[i].w){
                    d[nowNode]=d[nowV]+1;
                    if(nowNode==t)return 1;
                    q.push(nowNode);
                }
            }
        }
        return 0;
    }
    int Dinic(int x,int flow){
        if(x==t)return flow;
        int rest=flow;
        for(int i=head[x];i&&rest;i=e[i].nxt){
            int nowV=e[i].to;
            if(d[nowV]==d[x]+1&&e[i].w){
                int k=Dinic(nowV,min(rest,e[i].w));
                if(!k)d[nowV]=0;
                e[i].w-=k,e[i^1].w+=k;
                rest-=k;
            }
        }
        return flow-rest;
    }
    const int INF=2e9;
    int main(){
        int n,m,e;
        scanf("%d%d%d",&n,&m,&e);
        s=n+m+1,t=n+m+2;
        int u,v;
        for(int i=1;i<=n;i++){
        	addEdge(s,i,1);
        	addEdge(i,s,0);
    	}
        for(int i=1;i<=e;i++){
        	int u,v;
        	scanf("%d%d",&u,&v);
        	if(v>m||u>n)continue;
        	addEdge(u,v+n,1);
        	addEdge(v+n,u,0);//
    	}
    	for(int i=1;i<=m;i++){
    		addEdge(i+n,t,1);
    		addEdge(t,i+n,0);
    	}
        int ans=0;
        while(bfs()){
            ans+=Dinic(s,2e9);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    程序员励志语录
    javaEE的十一种技术
    gui内函数调用顺序
    m文件中函数的执行顺序
    VC++与Matlab混合编程之引擎操作详解(6)数据类型mxArray的操作
    GUI(2)
    时间管理
    Matlab GUI界面
    matlab GUI(2)
    MATLAB GUI平台
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680625.html
Copyright © 2020-2023  润新知