题意:~
思路:最小权匹配,跑两遍KM,第二次建边要处理每个工人第一次做工的时间差。
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PI; typedef pair< PI, int> PII; #define pb push_back #define Key_value ch[ch[root][1]][0] #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define MS(x,y) memset(x,y,sizeof(x)) const double eps = 1e-8; const double pi = acos (-1.0); const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const int M = 1000100; const int MAXN = 10010; const int MAXM = 100010; const int N = 310; int nx, ny; int g[N][N]; int linker[N], lx[N], ly[N]; int slack[N]; bool visx[N], visy[N]; bool DFS(int x) { visx[x] = true; 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] = true; if(linker[y] == -1 || DFS(linker[y])) { linker[y] = x; return true; } } else if(slack[y] > tmp) slack[y] = tmp; } return false; } 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, false, sizeof(visx)); memset(visy, false, 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; } struct mmp { int a, b, c; } wk[55]; int kk[50]; int mp[50][50]; int main() { int n; int casee = 1; while(~scanf("%d", &n), n) { int tmp; for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { scanf("%d", &tmp); g[i][j] = -tmp; } } nx = ny = n; KM(); for(int i = 1; i <= n; ++i) { wk[linker[i]].a = i; wk[linker[i]].c = -g[linker[i]][i]; } for(int i = 1; i <= n; ++i) { kk[i] = -g[linker[i]][i]; } for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { scanf("%d", &tmp); mp[i][j] = tmp; if(kk[j] - wk[i].c > 0) tmp += kk[j] - wk[i].c; g[i][j] = -tmp; } } KM(); for(int i = 1; i <= n; ++i) { wk[linker[i]].b = i; wk[linker[i]].c += -g[linker[i]][i]; } int time = 0; for(int i = 1; i <= n; ++i) { time += abs(mp[i][wk[i].b] + g[i][wk[i].b]); } printf("Case %d:\n", casee++); for(int i = 1; i <= n; ++i) { printf("Worker %d: %d %d %d\n", i, wk[i].a, wk[i].b, wk[i].c); } printf("Total idle time: %d\n", time); } return 0; } /* 4 8 6 12 19 13 2 18 10 9 15 16 17 5 18 4 10 2 6 3 3 8 5 9 2 5 8 4 3 4 4 5 2 0 */
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/1378 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!