• BZOJ5154 [Tjoi2014]匹配 【KM算法 + 枚举】


    题目链接

    BZOJ5154

    题解

    先跑出一个匹配方案
    然后暴力删去每对匹配再检验一下答案是否减小

    使用KM算法提升速度

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define pr pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 85,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int w[maxn][maxn],expa[maxn],expb[maxn],dl[maxn],cp[maxn],visa[maxn],visb[maxn];
    int n,tcp[maxn],mv,ansi;
    pr ans[maxn];
    bool dfs(int u){
    	visa[u] = true;
    	REP(i,n) if (!visb[i]){
    		int kl = expa[u] + expb[i] - w[u][i];
    		if (!kl){
    			visb[i] = true;
    			if (!cp[i] || dfs(cp[i])){
    				cp[i] = u; return true;
    			}
    		}
    		else dl[i] = min(dl[i],kl);
    	}
    	return false;
    }
    inline int work(){
    	REP(i,n) expa[i] = expb[i] = cp[i] = 0;
    	REP(i,n) REP(j,n) expa[i] = max(expa[i],w[i][j]);
    	REP(i,n){
    		REP(j,n) dl[j] = INF;
    		while (true){
    			REP(j,n) visa[j] = visb[j] = false;
    			if (dfs(i)) break;
    			int kl = INF;
    			REP(j,n) if (!visb[j]) kl = min(kl,dl[j]);
    			REP(j,n){
    				if (visa[j]) expa[j] -= kl;
    				if (visb[j]) expb[j] += kl;
    				else dl[j] -= kl;
    			}
    		}
    	}
    	int re = 0;
    	REP(i,n) re += w[cp[i]][i];
    	return re;
    }
    int main(){
    	n = read();
    	REP(i,n) REP(j,n) w[i][j] = read();
    	mv = work(); printf("%d
    ",mv);
    	REP(i,n) tcp[i] = cp[i];
    	REP(i,n){
    		int tmp = w[tcp[i]][i];
    		w[tcp[i]][i] = 0;
    		if (work() < mv) ans[++ansi] = mp(tcp[i],i);
    		w[tcp[i]][i] = tmp;
    	}
    	sort(ans + 1,ans + 1 + ansi);
    	REP(i,ansi) printf("%d %d
    ",ans[i].first,ans[i].second);
    	return 0;
    }
    
    
  • 相关阅读:
    SpringBoot系列之缓存使用教程
    Dubbo系列之常用配置用法简介
    SpringBoot系列之集成Dubbo的方式
    JavaScript系列之回调函数callback
    JavaScript系列之事件冒泡机制简介
    Oracle基础之保留字和关键字
    Oracle调优之no_unnest和unnest用法简介
    InnoSetup 以命令行自动编译打包
    InnoSetup 脚本打包及管理员权限设置
    C# 获取系统当前IE版本号
  • 原文地址:https://www.cnblogs.com/Mychael/p/9034659.html
Copyright © 2020-2023  润新知