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
", 1.0 * ans / n);
82     return 0;
83 }
View Code

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
", ans);
84     return 0;
85 }
View Code

  注意,把从食物向厨师连边比较快。

 

原文地址:https://www.cnblogs.com/y7070/p/5047842.html