在网上找了一份挺好的模板,先标一下哦~链接君:http://blog.csdn.net/abcjennifer/article/details/5844579
#include <iostream> #include <string.h> #include <algorithm> #include <iostream> using namespace std; int max(int a,int b) {return a<b?b:a;} int min(int a,int b) {return a<b?a:b;} const int size = 160; const int INF = 100000000; bool map[size][size]; // 二分图的相等子图, map[i][j] = true 代表Xi与Yj有边 bool sx[size], sy[size]; // 标记在一次DFS中,Xi与Yi是否在交错树上 int match[size]; // 保存匹配信息,其中i为Y中的顶点标号,match[i]为X中顶点标号 bool DFS(int, const int); void KM_Perfect_Match(const int n, const int edge[][size]) { int i, j; int lx[size], ly[size]; // KM算法中Xi与Yi的标号 for(i = 0; i < n; i++) { lx[i] = -INF; ly[i] = 0; for(j = 0; j < n; j++) { lx[i] = max(lx[i], edge[i][j]); } } bool perfect = false; while(!perfect) { // 初始化邻接矩阵 for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { if(lx[i]+ly[j] == edge[i][j]) map[i][j] = true; else map[i][j] = false; } } // 匹配过程 int live = 0; memset(match, -1, sizeof(match)); for(i = 0; i < n; i++) { memset(sx, false, sizeof(sx)); memset(sy, false, sizeof(sy)); if(DFS(i, n)) live++; else { sx[i] = true; break; } } if(live == n) perfect = true; else { // 修改标号过程 int ex = INF; for(i = 0; i < n; i++) { for(j = 0; sx[i] && j < n; j++) { if(!sy[j]) ex = min(ex, lx[i]+ly[j]-edge[i][j]); } } for(i = 0; i < n; i++) { if(sx[i]) lx[i] -= ex; if(sy[i]) ly[i] += ex; } } } } bool DFS(int p, const int n)//find augment path from X[p] { int i; for(i = 0; i < n; i++) { if(!sy[i] && map[p][i]) { sy[i] = true; int t = match[i]; match[i] = p; if(t == -1 || DFS(t, n)) { return true; } match[i] = t; if(t != -1) sx[t] = true; } } return false; } int main() { int n, edge[size][size]; // edge[i][j]为连接Xi与Yj的边的权值 int i; int m; /*************************************************** * record edge[i][j] as edge value between vertex i in X and vertex j in Y * save n as vertexs need to be match (used in KM_Perfect_Match(n, edge);) ***************************************************/ int s,d,pow; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0 && m==0) break; memset(edge,0,sizeof(edge)); /*最小权: 去掉memset(edge,0,sizeof(edge));改为如下: for(i=0;i<n;i++) for(int j=0;j<n;j++) edge[i][j]=-INF; */ memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); memset(match,0,sizeof(0)); while(m--) { scanf("%d%d%d",&s,&d,&pow); s--;d--; /*最小权:edge[s][d]=pow; 改为edge[s][d]= - pow;*/ edge[s][d]=pow; } KM_Perfect_Match(n, edge); int cost = 0; for(i=0;i<n;i++) { cost += edge[match[i]][i]; } /*最小权:output 改为 -cost*/ cout<<cost<<endl; } // cost 为最大匹配的总和, match[]中保存匹配信息 return 0; }
感觉这个模板也不错,比较符合审美。。。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int maxn = 105; const int inf = 0x3f3f3f3f; int N, L[maxn], Lx[maxn], Ly[maxn], W[maxn][maxn], slack[maxn]; bool S[maxn], T[maxn]; int match (int u) { S[u] = true; for (int i = 1; i <= N; i++) if (!T[i]) { if (Lx[u] + Ly[i] == W[u][i]) { T[i] = true; if (!L[i] || match(L[i])) { L[i] = u; return true; } } else slack[i] = min(slack[i], Lx[u]+Ly[i]-W[u][i]); } return false; } void update () { int a = inf; for (int i = 1; i <= N; i++) if (!T[i]) a = min(a, slack[i]); for (int i = 1; i <= N; i++) { if (S[i]) Lx[i] -= a; if (T[i]) Ly[i] += a; } } void KM () { for (int i = 1; i <= N; i++) { L[i] = Lx[i] = Ly[i] = 0; for (int j = 1; j <= N; j++) Lx[i] = max(Lx[i], W[i][j]); } for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) slack[j] = inf; while (true) { for (int j = 1; j <= N; j++) S[j] = T[j] = false; if (match(i)) break; else update(); } } } void init () { for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) W[i][j] = -inf; int u, v; for (int i = 1; i <= N; i++) { while (scanf("%d", &u) == 1 && u) { scanf("%d", &v); W[i][u] = max(W[i][u], -v); } } } int main () { while (scanf("%d", &N) == 1 && N) { init(); KM(); bool flag = false; for (int i = 1; i <= N; i++) { if (L[i] && W[L[i]][i] == -inf) flag = true; } if (flag) printf("N "); else { int ans = 0; for (int i = 1; i <= N; i++) ans += (Lx[i] + Ly[i]); printf("%d ", -ans); } } return 0; }