• 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

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

     

  • 相关阅读:
    SQL Injection
    yum命令不能使用的相关错误
    linux下RTNETLINK answers: File exists的解决方案
    XShell上传、下载文件(使用sz与rz命令)!
    Linux中iptables设置详细
    linux shell awk用法
    linux sed命令 用法
    Tcpdump 的用法
    VIM文本替换命令
    linux的tar命令详情;linux多个文件压缩打包到一个压缩文件
  • 原文地址:https://www.cnblogs.com/y7070/p/5047842.html
Copyright © 2020-2023  润新知