【HDOJ】2853 Assignment
最小费用最大流可解最优解。至于dif如何解,可以把w扩大100倍,如果mission编号和排列P相等则对w+1,然后建立网络流。
对结果取模100可以得到没有改变mission的company数目,用company数目减之可以得到dif.
1 /* 2853 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 const int INF = 0x1f1f1f1f; 43 const int maxn = 55; 44 const int maxv = maxn * 2; 45 const int maxe = maxv * maxv * 5; 46 int V[maxe], F[maxe], W[maxe], nxt[maxe]; 47 int head[maxv], dis[maxv], pre[maxv], ID[maxv]; 48 bool visit[maxv]; 49 int M[maxn][maxn], P[maxn]; 50 int s, t, m; 51 52 void addEdge(int u, int v, int f, int w) { 53 V[m] = v; 54 F[m] = f; 55 W[m] = w; 56 nxt[m] = head[u]; 57 head[u] = m++; 58 59 V[m] = u; 60 F[m] = 0; 61 W[m] = -w; 62 nxt[m] = head[v]; 63 head[v] = m++; 64 } 65 66 bool bfs() { 67 queue<int> Q; 68 int u, v, k; 69 70 memset(dis, INF, sizeof(dis)); 71 memset(visit, false, sizeof(visit)); 72 Q.push(s); 73 dis[s] = 0; 74 75 while (!Q.empty()) { 76 u = Q.front(); 77 Q.pop(); 78 visit[u] = false; 79 for (k=head[u]; k!=-1; k=nxt[k]) { 80 v = V[k]; 81 if (F[k] && dis[v]>dis[u]+W[k]) { 82 dis[v] = dis[u] + W[k]; 83 ID[v] = k; 84 pre[v] = u; 85 if (!visit[v]) { 86 visit[v] = true; 87 Q.push(v); 88 } 89 } 90 } 91 } 92 93 return dis[t]==INF; 94 } 95 96 int MCMF() { 97 int ret = 0, tmp; 98 int u, v, k; 99 100 while (1) { 101 if (bfs()) 102 break; 103 104 tmp = INF; 105 for (v=t, u=pre[v]; v!=s; v=u, u=pre[v]) { 106 k = ID[v]; 107 tmp = min(F[k], tmp); 108 } 109 110 for (v=t, u=pre[v]; v!=s; v=u, u=pre[v]) { 111 k = ID[v]; 112 F[k] -= tmp; 113 F[k^1] += tmp; 114 } 115 116 ret += dis[t] * tmp; 117 } 118 119 return ret; 120 } 121 122 123 int main() { 124 ios::sync_with_stdio(false); 125 #ifndef ONLINE_JUDGE 126 freopen("data.in", "r", stdin); 127 freopen("data.out", "w", stdout); 128 #endif 129 130 int r, c; 131 int ans, tot, tmp, dif; 132 133 while (scanf("%d %d", &r, &c) != EOF) { 134 135 s = m = 0; 136 t = r + c + 1; 137 memset(head, -1, sizeof(head)); 138 139 rep(i, 1, r+1) 140 rep(j, 1, c+1) 141 scanf("%d", &M[i][j]); 142 rep(i, 1, r+1) 143 scanf("%d", &P[i]); 144 145 rep(i, 1, r+1) 146 addEdge(s, i, 1, 0); 147 148 rep(j, 1, c+1) 149 addEdge(j+r, t, 1, 0); 150 151 tot = 0; 152 rep(i, 1, r+1) { 153 rep(j, 1, c+1) { 154 if (j == P[i]) { 155 tmp = M[i][j] * 100 + 1; 156 } else { 157 tmp = M[i][j] * 100; 158 } 159 addEdge(i, j+r, 1, -tmp); 160 } 161 tot += M[i][P[i]]; 162 } 163 164 tmp = -MCMF(); 165 ans = tmp/100 - tot; 166 #ifndef ONLINE_JUDGE 167 printf("tot = %d, MCMF = %d\n", tot, tmp); 168 #endif 169 dif = r - tmp%100; 170 printf("%d %d\n", dif, ans); 171 } 172 173 #ifndef ONLINE_JUDGE 174 printf("time = %d.\n", (int)clock()); 175 #endif 176 177 return 0; 178 }