• HDU2255 【模板】KM算法


    题目地址


    KM算法

    易错点:

    • 配不上的话可能连机会都没有了,所以不要太天真(vb[y]=1(占有)要在配得上(gap==0,门当户对)的前提下).
    • 没缘分的话最好就不要妄想(if(vb[y])continue;).

    费用流算法

    (qwq)


    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=310,INF=1<<30;
    int la[N],lb[N],w[N][N],match[N],delta,n;
    bool va[N],vb[N];
    bool dfs(int x){
    	va[x]=1;
    	for(int y=1;y<=n;y++){
    		if(vb[y])continue;
    		int gap=la[x]+lb[y]-w[x][y];
    		if(gap==0){
    			vb[y]=1;
    			if(!match[y]||dfs(match[y])){
    				match[y]=x;
    				return 1;
    			}
    		}else delta=min(delta,gap);
    	}
    	return 0;
    }
    int KM(){
    	for(int x=1;x<=n;x++){
    		la[x]=-INF;
    		for(int y=1;y<=n;y++)
    			la[x]=max(la[x],w[x][y]);
    	}
    	for(int x=1;x<=n;x++){
    		while(1){
    			memset(va,0,sizeof(va));
    			memset(vb,0,sizeof(vb));
    			delta=INF;
    			if(dfs(x))break;
    			for(int i=1;i<=n;i++){
    				if(va[i])la[i]-=delta;
    				if(vb[i])lb[i]+=delta;
    			}
    		}
    	}
    	int ans=0;
    	for(int y=1;y<=n;y++)
    		ans+=w[match[y]][y];
    	return ans;
    }
    void init(){
    	memset(lb,0,sizeof(lb));
    	memset(match,0,sizeof(match));
    }
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		init();
    		for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			scanf("%d",&w[i][j]);
    		printf("%d
    ",KM());
    	}
    	return 0;
    }
  • 相关阅读:
    【杭电】[4857]逃生
    【杭电】[2647]Reward
    【杭电】[1285]确定比赛名次
    【杭电】[1251]统计难题
    OJ系统上线——OJ.BoilTask.com
    【郑轻】[1893]985的数学难题
    【郑轻】[1900]985的“树”难题
    【郑轻】[1898]985的数字难题
    HDU 1850———nim博弈
    HDU 2188------巴什博弈
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680592.html
Copyright © 2020-2023  润新知