二分图的最佳完美匹配(模板)
生活随笔
收集整理的這篇文章主要介紹了
二分图的最佳完美匹配(模板)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
??????? 二分圖的最佳完美匹配,也就是帶權(quán)值的無(wú)向二分圖中權(quán)值之和最大的完美匹配,整個(gè)圖分為兩個(gè)不相交的集合x(chóng)和y,采用KM算法求解,也稱匈牙利算法. 時(shí)間復(fù)雜度為O(n^3)
typedef int type;//實(shí)際數(shù)據(jù)類型,一般是int或doubleconst type inf = 2e9; const double eps = 1e-8; const int maxn = 330;int n, m;//x中結(jié)點(diǎn)個(gè)數(shù),y中結(jié)點(diǎn)個(gè)數(shù),下標(biāo)從0開(kāi)始 int matchx[maxn], matchy[maxn];//matchx[i]指的是xi匹配到的y中結(jié)點(diǎn)的編號(hào),matchy[j]指的是yj匹配到的x中結(jié)點(diǎn)的編號(hào) int visx[maxn], visy[maxn];//訪問(wèn)標(biāo)記數(shù)組 type lx[maxn], ly[maxn];//x,y中每個(gè)點(diǎn)的期望值 type w[maxn][maxn];//類似鄰接矩陣w[x][y]表示x到y(tǒng)有權(quán)值為w[x][y]的邊 type slack[maxn];//y中每個(gè)元素的slack值bool dfs(int x) {visx[x] = 1;for (int y = 0; y < m; ++y) {if (visy[y]) continue;type tmp = lx[x] + ly[y] - w[x][y];if (tmp == 0) {//double的話改成: if (fabs(tmp)<=eps)visy[y] = 1;if (matchy[y] == -1 || dfs(matchy[y])) {matchx[x] = y;matchy[y] = x;return true;}}else {slack[y] = min(slack[y], tmp);}}return false; }void KM() {memset(matchy, -1, sizeof(matchy));memset(ly, 0, sizeof(ly));for (int i = 0; i < n; ++i) {lx[i] = -inf;for (int j = 0; j < m; ++j) {lx[i] = max(lx[i], w[i][j]);}}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) slack[j] = inf;while (1) {memset(visx, 0, sizeof(visx));memset(visy, 0, sizeof(visy));if (dfs(i)) break;type d = inf;for (int j = 0; j < m; ++j) {if (!visy[j]) d = min(d, slack[j]);}for (int j = 0; j < n; ++j) { if (visx[j]) lx[j] -= d; }for (int j = 0; j < m; ++j) {if (visy[j]) ly[j] += d;else slack[j] -= d;}}} }??????? 模板題 hdu2255 http://acm.hdu.edu.cn/showproblem.php?pid=2255
??????? 中文題目,裸的二分圖最佳完美匹配問(wèn)題
#include<bits/stdc++.h> using namespace std;typedef int type;const type inf = 2e9; const double eps = 1e-8; const int maxn = 330;int n, m; int matchx[maxn], matchy[maxn]; int visx[maxn], visy[maxn]; type lx[maxn], ly[maxn]; type w[maxn][maxn]; type slack[maxn];bool dfs(int x) {visx[x] = 1;for (int y = 0; y < m; ++y) {if (visy[y]) continue;type tmp = lx[x] + ly[y] - w[x][y];if (tmp == 0) {visy[y] = 1;if (matchy[y] == -1 || dfs(matchy[y])) {matchx[x] = y;matchy[y] = x;return true;}}else {slack[y] = min(slack[y], tmp);}}return false; }void KM() {memset(matchy, -1, sizeof(matchy));memset(ly, 0, sizeof(ly));for (int i = 0; i < n; ++i) {lx[i] = -inf;for (int j = 0; j < m; ++j) {lx[i] = max(lx[i], w[i][j]);}}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) slack[j] = inf;while (1) {memset(visx, 0, sizeof(visx));memset(visy, 0, sizeof(visy));if (dfs(i)) break;type d = inf;for (int j = 0; j < m; ++j) {if (!visy[j]) d = min(d, slack[j]);}for (int j = 0; j < n; ++j) { if (visx[j]) lx[j] -= d; }for (int j = 0; j < m; ++j) {if (visy[j]) ly[j] += d;else slack[j] -= d;}}} }int main() {while (scanf("%d", &n) == 1) {m = n;for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {scanf("%d", &w[i][j]);}}KM();int ans = 0;for (int i = 0; i < n; ++i) {ans += w[i][matchx[i]];}printf("%d\n", ans);}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/wafish/p/10465361.html
總結(jié)
以上是生活随笔為你收集整理的二分图的最佳完美匹配(模板)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 吃烧烤时如何配上美味的烤串?
- 下一篇: 自动瘦脸与眼睛放大美颜算法