KM hdu2255 奔小康賺大錢
阿新 • • 發佈:2019-01-08
題意:最裸的帶權二分圖匹配。
思路:KM演算法,複雜度為O(n^3),比費用流的效率要快一些,所以有時候必須用KM演算法。
但是KM演算法的適用範圍比較小,要學會去分辨.
#include <map> #include <set> #include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #include <functional> #define fuck(x) cout<<"["<<x<<"]"; #define FIN freopen("input.txt","r",stdin); #define FOUT freopen("output.txt","w+",stdout); //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MX = 3e2 + 5; /* KM演算法 * 複雜度O(nx*nx*ny) * 求最大權匹配 * 若求最小權匹配,可將權值取相反數,結果取相反數 * 點的編號從1開始 */ const int INF = 0x3f3f3f3f; int nx, ny; //兩邊的點數 int G[MX][MX];//二分圖描述 int linker[MX], lx[MX], ly[MX]; //y中各點匹配狀態,x,y中的點標號 int slack[MX]; bool visx[MX], visy[MX]; bool DFS(int x) { visx[x] = 1; for(int y = 1; y <= ny; y++) { if(visy[y]) continue; int tmp = lx[x] + ly[y] - G[x][y]; if(tmp == 0) { visy[y] = 1; if(linker[y] == -1 || DFS(linker[y])) { linker[y] = x; return 1; } } else if(slack[y] > tmp) { slack[y] = tmp; } } return 0; } int KM() { memset(linker, -1, sizeof(linker)); memset(ly, 0, sizeof(ly)); for(int i = 1; i <= nx; i++) { lx[i] = -INF; for(int j = 1; j <= ny; j++) { if(G[i][j] > lx[i]) lx[i] = G[i][j]; } } for(int x = 1; x <= nx; x++) { for(int i = 1; i <= ny; i++) slack[i] = INF; while(true) { memset(visx, 0, sizeof(visx)); memset(visy, 0, sizeof(visy)); if(DFS(x)) break; int d = INF; for(int i = 1; i <= ny; i++) { if(!visy[i] && d > slack[i]) d = slack[i]; } for(int i = 1; i <= nx; i++) { if(visx[i]) lx[i] -= d; } for(int i = 1; i <= ny; i++) { if(visy[i]) ly[i] += d; else slack[i] -= d; } } } int res = 0; for(int i = 1; i <= ny; i++) { if(linker[i] != -1) res += G[linker[i]][i]; } return res; } int main() { int n; //FIN; while(~scanf("%d", &n)) { for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { scanf("%d", &G[i][j]); } } nx = ny = n; printf("%d\n", KM()); } return 0; }