bzoj1070 修车&& bzoj2879美食节 【费用流】
bzoj1070:
把每个工人拆成汽车那么多个点,假如说 工人(i, j) 和 汽车k 连边,那就代表第i个工人倒数第j个修汽车k,那么这条边对以后的贡献就是k*time[i修k]。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define mp make_pair 6 #define pb push_back 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = ~0U >> 1; 14 const i64 INF = ~0ULL >> 1; 15 //********************************* 16 17 const int maxn = 605, maxm = 33005; 18 19 struct Ed { 20 int u, v, nx, c, w; Ed() {} 21 Ed(int _u, int _v, int _nx, int _c, int _w) : 22 u(_u), v(_v), nx(_nx), c(_c), w(_w) {} 23 } E[maxm << 1]; 24 int G[maxn], edtot; 25 void addedge(int u, int v, int c, int w) { 26 E[edtot] = (Ed){u, v, G[u], c, w}; 27 G[u] = edtot++; 28 E[edtot] = (Ed){v, u, G[v], 0, -w}; 29 G[v] = edtot++; 30 } 31 32 bool vis[maxn]; int dis[maxn], s, t; 33 bool spfa() { 34 static int que[maxm]; int qh(0), qt(0); 35 rep(i, s, t) vis[i] = 0, dis[i] = 0x3f3f3f3f; 36 dis[que[++qt] = s] = 0; vis[s] = 1; 37 while (qh != qt) { 38 int x = que[++qh]; vis[x] = 0; 39 for (int i = G[x]; i != -1; i = E[i].nx) { 40 if (E[i].c && dis[E[i].v] > dis[x] + E[i].w) { 41 dis[E[i].v] = dis[x] + E[i].w; 42 if (!vis[E[i].v]) vis[que[++qt] = E[i].v] = 1; 43 } 44 } 45 } 46 return dis[t] != 0x3f3f3f3f; 47 } 48 int ans, cur[maxn]; 49 int dfs(int u, int rm) { 50 vis[u] = 1; 51 if (u == t) return rm; 52 int rm1 = rm; 53 for (int &i = cur[u]; i != -1; i = E[i].nx) { 54 if (E[i].c && !vis[E[i].v] && dis[E[i].v] == dis[u] + E[i].w) { 55 int flow = dfs(E[i].v, min(rm, E[i].c)); 56 E[i].c -= flow, E[i ^ 1].c += flow; 57 ans += flow * E[i].w; 58 if ((rm -= flow) == 0) break; 59 } 60 } 61 if (rm1 == rm) dis[u] = 0; 62 return rm1 - rm; 63 } 64 65 int a[65][10]; 66 int main() { 67 int m, n; scanf("%d%d", &m, &n); 68 rep(i, 1, n) rep(j, 1, m) scanf("%d", &a[i][j]); 69 s = 0, t = n + n * m + 1; 70 memset(G, -1, sizeof(G)); 71 rep(i, 1, n) addedge(s, i, 1, 0); 72 rep(i, n + 1, n + n * m) addedge(i, t, 1, 0); 73 rep(i, 1, n) { 74 rep(j, 1, m) { 75 rep(k, 1, n) { 76 addedge(i, n + (j - 1) * n + k, 1, k * a[i][j]); 77 } 78 } 79 } 80 while (spfa()) memcpy(cur, G, sizeof(G)),dfs(s, 0x3f3f3f3f); 81 printf("%.2lf\n", 1.0 * ans / n); 82 return 0; 83 }
bzoj2879:
首先把每个食物和厨师连边,一开始只用和每个厨师的倒数第一这个时间段连边,如果用了的话再用这个厨师的倒数第二去连边。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = ~0U >> 1; 14 const i64 INF = ~0ULL >> 1; 15 //********************************** 16 17 const int maxn = 100005, maxm = 3000005; 18 19 struct Ed { 20 int u, v, nx, c, w; Ed() {} 21 Ed(int _u, int _v, int _nx, int _c, int _w) : 22 u(_u), v(_v), nx(_nx), c(_c), w(_w) {} 23 } E[maxm]; 24 int G[maxn], edtot = 1; 25 void addedge(int u, int v, int c, int w) { 26 E[++edtot] = Ed(u, v, G[u], c, w); 27 G[u] = edtot; 28 E[++edtot] = Ed(v, u, G[v], 0, -w); 29 G[v] = edtot; 30 } 31 32 int tot, n, m; 33 34 bool vis[maxn]; int dis[maxn], s, t, pre[maxn]; 35 bool spfa() { 36 static int que[maxn]; int qh(0), qt(0); 37 rep(i, s, t) vis[i] = 0, dis[i] = inf; 38 vis[que[++qt] = s] = 1, dis[s] = 0; 39 while (qh != qt) { 40 int x = que[++qh]; if (qh == t) qh = 0; 41 for (int i = G[x]; i; i = E[i].nx) { 42 if (E[i].c && dis[E[i].v] > dis[x] + E[i].w) { 43 dis[E[i].v] = dis[x] + E[i].w; 44 pre[E[i].v] = i; 45 if (!vis[E[i].v]) { 46 vis[que[++qt] = E[i].v] = 1; 47 if (qt == t) qt = 0; 48 } 49 } 50 } 51 vis[x] = 0; 52 } 53 return dis[t] != inf; 54 } 55 int a[45][105]; 56 int ans; 57 void mcf() { 58 int flow = inf, x, y; 59 for (int i = pre[t]; i; i = pre[E[i].u]) { 60 flow = min(flow, E[i].c); 61 if (E[i].v == t) { 62 x = (E[i].u - 1) / tot + 1; y = E[i].u % tot + 1; 63 } 64 } 65 for (int i = pre[t]; i; i = pre[E[i].u]) { 66 E[i].c -= flow, E[i ^ 1].c += flow, ans += flow * E[i].w; 67 } 68 addedge((x - 1) * tot + y, t, 1, 0); 69 for (int i = 1; i <= n; i++) 70 addedge(m * tot + i, (x - 1) * tot + y, 1, y * a[i][x]); 71 } 72 73 int main() { 74 scanf("%d%d", &n, &m); 75 static int c[45]; 76 rep(i, 1, n) scanf("%d", c + i), tot += c[i]; 77 rep(i, 1, n) rep(j, 1, m) scanf("%d", &a[i][j]); 78 s = 0, t = m * tot + n + 1; 79 rep(i, 1, n) addedge(s, m * tot + i, c[i], 0); 80 rep(i, 1, m) addedge((i - 1) * tot + 1, t, 1, 0); 81 rep(i, 1, m) rep(j, 1, n) addedge(m * tot + j, (i - 1) * tot + 1, 1, a[j][i]); 82 while (spfa()) mcf(); 83 printf("%d\n", ans); 84 return 0; 85 }
注意,把从食物向厨师连边比较快。