二分图最小权值匹配KM算法~

View Code
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include <assert.h>
6 #include <ctype.h>
7 #include <map>
8 #include <string>
9 #include <set>
10 #include <bitset>
11 #include <utility>
12 #include <algorithm>
13 #include <vector>
14 #include <stack>
15 #include <queue>
16 #include <iostream>
17 #include <fstream>
18 #include <list>
19
20 usingnamespace std;
21
22 constint MAXN =128;
23 constint INF =1000000000;
24
25 int N;
26 int g[MAXN][MAXN];
27 int pre[MAXN];
28 int lx[MAXN], ly[MAXN], slack[MAXN];
29 bool visx[MAXN], visy[MAXN];
30
31 int data[MAXN][MAXN];
32
33 void BuildGraph()
34 {
35 int i, j, k, nr, nc;
36
37 scanf("%d %d",&nc,&nr);
38 for (i =0;i < nr;i++)
39 for (j =0;j < nc;j++)
40 scanf("%d",&data[i][j]);
41
42 N = nc;
43
44 for (i =0; i < N; i++)
45 for (j =0; j < N; j++)
46 {
47 int sum =0;
48 for (k =0;k < nr;k++)
49 sum += abs(i+1-data[k][j]);
50 g[i][j] =-sum;
51 }
52 }
53
54 bool dfs(int t)
55 {
56 int i;
57 visx[t] =true;
58 for (i =0; i < N; i++)
59 {
60 if (visy[i]) continue;
61 int tmp = lx[t]+ly[i]-g[t][i];
62 if (tmp ==0)
63 {
64 visy[i] =true;
65 if (pre[i] ==-1|| dfs(pre[i]))
66 {
67 pre[i] = t;
68 returntrue;
69 }
70 }
71 elseif (slack[i] > tmp)
72 {
73 slack[i] = tmp;
74 }
75 }
76 returnfalse;
77 }
78 int KM()
79 {
80 int i, j;
81 memset(pre, -1, sizeof(pre));
82 memset(ly, 0, sizeof(ly));
83 for(i =0; i < N; i++)
84 lx[i] =-INF;
85 for(i =0; i < N; i++)
86 {
87 for(j =0; j < N; j++)
88 {
89 if(lx[i] < g[i][j])
90 lx[i] = g[i][j];
91 }
92 }
93 for(i =0; i < N; i++)
94 {
95 for(j =0; j < N; j++)
96 slack[j] = INF;
97 while(1)
98 {
99 memset(visx, false, sizeof(visx));
100 memset(visy, false, sizeof(visy));
101 if(dfs(i)) break;
102 int d = INF;
103 for(j =0; j < N; j++)
104 if(!visy[j] && slack[j] < d)
105 d = slack[j];
106 for(j =0; j < N; j++)
107 if(visx[j]) lx[j] -= d;
108 for(j =0; j < N; j++)
109 {
110 if(visy[j]) ly[j] += d;
111 else slack[j] -= d;
112 }
113 }
114 }
115 int ans =0;
116 for(i =0; i < N; i++)
117 {
118 if(pre[i] !=-1)
119 ans -= g[pre[i]][i];
120 }
121 return ans;
122 }
123
124
125 int main()
126 {
127 int T;
128 scanf("%d", &T);
129 for(int cc =1;cc <= T;cc++)
130 {
131 BuildGraph();
132 int ans = KM();
133 printf("Case #%d: %d\n", cc, ans);
134 }
135 return0;
136 }