• 两种求二分图匹配的姿势


    UOJ #78. 二分图最大匹配

    从前一个和谐的班级,有 nl 个是男生,有 nr 个是女生。编号分别为 1,,nl 和 1,,nr

    有若干个这样的条件:第 v 个男生和第 u 个女生愿意结为配偶。

    请问这个班级里最多产生多少对配偶?

    输入格式

    第一行三个正整数,nl,nr,m

    接下来 m 行,每行两个整数 v,表示第 v 个男生和第 u 个女生愿意结为配偶。保证 1vnl1unr,保证同一个条件不会出现两次。

    输出格式

    第一行一个整数,表示最多产生多少对配偶。

    接下来一行 nl 个整数,描述一组最优方案。第 v 个整数表示 v 号男生的配偶的编号。如果 v 号男生没配偶请输出 0。

    样例一

    input

    2 2 3
    1 1
    1 2
    2 1
    
    

    output

    2
    2 1
    
    

    explanation

    1 号男生跟 2 号女生幸福地生活在了一起~

    2 号男生跟 1 号女生幸福地生活在了一起~

    样例二

    input

    2 2 2
    1 1
    2 1
    
    

    output

    1
    1 0
    
    

    explanation

    班上一个女神一个女汉子,两个男生都去追女神。一种最优方案是:

    1 号男生跟 1 号女生幸福地生活在了一起~

    2 号男生孤独终生。= =||

    限制与约定

    1nl,nr5001m250000

    时间限制1s

    空间限制256MB

    下载

    样例数据下载

    最大流dinic算法

    #include<cstdio>
    #include<queue>
    #include<iostream>
    #define INF 2147483647
    #define BIG 1000011
    std::queue<int>q;
    int nxt[BIG],las[BIG],to[BIG],w[BIG],dep[BIG];
    int nl,nr,m,tot=1;
    int x,y,S,T;
    inline void add(int x,int y,int z){
    	nxt[++tot]=las[x];
    	las[x]=tot;
    	to[tot]=y;
    	w[tot]=z;
    }
    inline int bfs(){
    	for(register int i=1;i<=T;++i)
    		dep[i]=0;
    	dep[S]=1;
    	q.push(S);
    	int now;
    	while(!q.empty()){
    		now=q.front();
    		q.pop();
    		for(register int e=las[now];e;e=nxt[e])
    			if(w[e]&&!dep[to[e]]){
    				dep[to[e]]=dep[now]+1;
    				q.push(to[e]);
    			}
    	}
    	return dep[T];
    }
    inline int dfs(int now,int f){
    	if(now==T)
    		return f;
    	int ret=0,d;
    	for(register int e=las[now];e&&f;e=nxt[e])
    		if(w[e]&&dep[to[e]]==dep[now]+1){
    			d=dfs(to[e],std::min(w[e],f));
    			f-=d;
    			ret+=d;
    			w[e]-=d;
    			w[e^1]+=d;
    		}
    	if(!ret)
    		dep[now]=0;
    	return ret;
    }
    inline int dinic(){
    	int ans=0;
    	while(bfs())
    		ans+=dfs(S,INF);
    	return ans;
    }
    int main(){
    	scanf("%d%d%d",&nl,&nr,&m);
    	S=nl+nr+1;
    	T=nl+nr+2;
    	for(register int i=1;i<=nl;++i)
    		add(S,i,1),add(i,S,0);
    	for(register int i=nl+1;i<=nl+nr;++i)
    		add(i,T,1),add(T,i,0);
    	for(register int i=1;i<=m;++i){
    		scanf("%d%d",&x,&y);
    		add(x,y+nl,1),add(y+nl,x,0);
    	}
    	printf("%d
    ",dinic());
    	for(register int i=1;i<=nl;++i){
    		for(register int e=las[i];e;e=nxt[e])
    			if(!w[e]&&to[e]!=S){
    				printf("%d",to[e]-nl);
    				putchar(' ');
    				goto sign;
    			}
    		putchar(48);
    		putchar(' ');
    		sign:;
    	}
    	return 0;
    }
    

      

     

    匈牙利算法

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    #define BIG 1000011
    using namespace std;
    int n,m,t,x,y,tot,ans,cnt;
    int nxt[BIG],las[BIG],to[BIG],vis[BIG],con[BIG],have[BIG];
    inline void add(int x,int y){
    	nxt[++tot]=las[x];
    	las[x]=tot;
    	to[tot]=y;
    }
    inline int match(int now){
    	for(register int e=las[now];e;e=nxt[e])
    		if(!vis[to[e]]){
    			vis[to[e]]=1;
    			have[++cnt]=to[e];
    			if(!con[to[e]]||match(con[to[e]])){
    				con[to[e]]=now;
    				return 1;
    			}
    		}
    	return 0;
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&t);
    	while(t--){
    		scanf("%d%d",&x,&y);
    		add(y+n,x);
    	}
    	FOR(j,n+1,n+m){
    		while(cnt)
    			vis[have[cnt--]]=0;
    		ans+=match(j);
    	}
    	printf("%d
    ",ans);
    	FOR(i,1,n)
    		printf("%d ",con[i]?con[i]-n:con[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    autocare使用命令
    使用国内豆瓣源
    HCNA(二)以太网的帧结构
    HCNA(一)网络传输介质
    Python
    Python
    Python
    Delphi
    HCNP
    Python
  • 原文地址:https://www.cnblogs.com/Stump/p/7687583.html
Copyright © 2020-2023  润新知