• 二分图匹配的两个主要算法 模板


    匈牙利算法

    模板题

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    const int MAXN = 503;
    
    int n, m;
    bool to[MAXN][MAXN];
    
    int xchoice[MAXN];
    int ychoice[MAXN];
    
    bool vis[MAXN];
    
    bool match(int x) {
    	for (int y = 1; y <= m; y ++) {
    		if (to[x][y] == false) continue;
    		if (vis[y]) continue;
    		vis[y] = true;
    		if (ychoice[y] == 0 || match(ychoice[y])) {
    			ychoice[y] = x;
    			return true;
    		}
    	}
    	return false;
    }
    
    int main() {
    	int e;
    	scanf("%d%d%d", &n, &m, &e);
    
    	for (int i = 0; i < e; i ++) {
    		int x, y;
    		scanf("%d%d", &x, &y);
    		to[x][y] = true;
    	}
    
    	int ans = 0;
    	for (int i = 1; i <= n; i ++) {
    		fill(vis + 1, vis + 1 + m, false);
    		if (match(i)) {
    			ans ++;
    		}
    	}
    	printf("%d
    ", ans);
    	for (int i = 1; i <= m; i ++)
    		xchoice[ychoice[i]] = i;
    	for (int i = 1; i <= n; i ++)
    		printf("%d ", xchoice[i]);
    	printf("
    ");
    
    	return 0;
    }
    
    

    KM算法

    据说KM算法只能用在完备匹配,我想应该不是这样的吧。

    这一题就是一个很好的例子。

    对不起,我想错了QAQ,KM算法确实是只能用在完备匹配。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    const int MAXN = 403;
    const double INF = 1e100;
    const double EPS = 1e-12;
    
    template <class T>
    T sqr(const T &x) {
    	return x * x;
    }
    
    template <class T>
    void tension(T &a, const T &b) {
    	if (b < a) a = b;
    }
    
    template <class T>
    void relax(T &a, const T &b) {
    	if (b > a) a = b;
    }
    
    int n, root;
    
    double dis(int x1, int y1, int x2, int y2) {
    	return sqrt(sqr(x1 - x2) + sqr(y1 - y2));
    }
    
    double to[MAXN][MAXN * 2];
    double A[MAXN], B[MAXN * 2];
    double slack[MAXN * 2];
    int ychoice[MAXN * 2];
    bool visx[MAXN], visy[MAXN * 2];
    
    bool match(int x) {
    	visx[x] = true;
    	for (int y = 0; y < n << 1; y ++) {
    		if (to[x][y] > - EPS) continue;
    		if (visy[y]) continue;
    		if (abs(to[x][y] - A[x] - B[y]) <= EPS) {
    			visy[y] = true;
    			if (ychoice[y] == -1 || match(ychoice[y])) {
    				ychoice[y] = x;
    				return true;
    			}
    		}
    		else {
    			tension(slack[y], A[x] + B[y] - to[x][y]);
    		}
    	}
    	return false;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("input.txt", "r", stdin);
    #endif
    
    	scanf("%d", &n);
    	static int x[MAXN], y[MAXN];
    	int cnt = 0;
    	root = 0;
    	for (int i = 0; i < n; i ++) {
    		scanf("%d%d", x + i, y + i);
    		if (y[i] > y[root]) {
    			root = i;
    			cnt = 1;
    		}
    		else if (y[i] == y[root]) {
    			cnt ++;
    		}
    	}
    	if (cnt != 1) {
    		printf("-1
    ");
    		return 0;
    	}
    
    	for (int i = 0; i < n; i ++) {
    		if (i == root) continue;
    		for (int j = 0; j < n; j ++) {
    			if (! (y[j] > y[i])) continue;
    			to[i][j] = to[i][j + n] = - dis(x[i], y[i], x[j], y[j]);
    		}
    	}
    
    	fill(A, A + n, - INF);
    	fill(ychoice, ychoice + (n << 1), -1);
    	for (int i = 0; i < n; i ++)
    		for (int j = 0; j < n << 1; j ++) {
    			if (to[i][j] > - EPS) continue;
    			relax(A[i], to[i][j]);
    		}
    	for (int i = 0; i < n; i ++) {
    		if (i == root) continue;
    		while (true) {
    			//cerr << i<< endl;
    			fill(visx, visx + n, false);
    			fill(visy, visy + (n << 1), false);
    			fill(slack, slack + (n << 1), INF);
    			if (match(i)) break;
    			double tmp = INF;
    			for (int y = 0; y < n << 1; y ++)
    				if (! visy[y]) tension(tmp, slack[y]);
    			if (tmp + EPS >= INF) {
    				printf("-1
    ");
    				return 0;
    			}
    			for (int x = 0; x < n; x ++)
    				if (visx[x]) A[x] -= tmp;
    			for (int y = 0; y < n << 1; y ++)
    				if (visy[y]) B[y] += tmp;
    		}
    	}
    	double ans = 0;
    	for (int y = 0; y < n << 1; y ++)
    		if (ychoice[y] != -1)
    			ans += to[ychoice[y]][y];
    	printf("%.10lf
    ", - ans);
    
    	return 0;
    }
    
  • 相关阅读:
    【POJ】【2104】区间第K大
    【BZOJ】【2595】【WC2008】游览计划
    【BZOJ】【1036】树的统计
    【BZOJ】【2038】小Z的袜子
    我的博客~
    CSS选择器
    CSS样式表分类
    python奇闻杂技03 三元表达式示例,函数定义示例,七段彩码管绘制示例
    python奇闻杂技02 time模块,文本进度条示例,数字类型操作,字符串操作
    python奇闻杂技01 turtle学习
  • 原文地址:https://www.cnblogs.com/wangck/p/4369596.html
Copyright © 2020-2023  润新知