• 最大流最小割费用流初步


    2015年11月23日

      网络流24题<1> COGS 14

        二分图匹配。

        Dinic:

     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 = 105;
    18 struct Ed {
    19     int u, v, nx, c; Ed() {}
    20     Ed(int _u, int _v, int _nx, int _c) :
    21         u(_u), v(_v), nx(_nx), c(_c) {}
    22 } E[3005];
    23 int G[105], cnt;
    24 void addedge(int x, int y, int v) {
    25     E[cnt] = Ed(x, y, G[x], v);
    26     G[x] = cnt++;
    27     E[cnt] = Ed(y, x, G[y], 0);
    28     G[y] = cnt++;
    29 }
    30 
    31 int s, t;
    32 
    33 int level[maxn];
    34 bool bfs() {
    35     static int que[maxn]; int qt(0), qh(0);
    36     clr(level);
    37     level[que[++qt] = s] = 1;
    38     while (qt != qh) {
    39         int x = que[++qh];
    40         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
    41             level[que[++qt] = E[i].v] = level[x] + 1;
    42     }
    43     return !!level[t];
    44 }
    45 int dfs(int u, int rm) {
    46     if (u == t) return rm;
    47     int rm1 = rm;
    48     for (int i = G[u]; i != -1; i = E[i].nx) {
    49         if (E[i].c && level[E[i].v] == level[u] + 1) {
    50             int flow = dfs(E[i].v, min(E[i].c, rm));
    51             E[i].c -= flow, E[i ^ 1].c += flow;
    52             if ((rm -= flow) == 0) break;
    53         }
    54     }
    55     if (rm1 == rm) level[u] = 0;
    56     return rm1 - rm;
    57 }
    58 
    59 int main() {
    60     freopen("flyer.in", "r", stdin);
    61     freopen("flyer.out", "w", stdout);
    62     int n, n1;
    63     while (~scanf("%d%d", &n, &n1)) {
    64         s = 0, t = n + 1;
    65         memset(G, -1, sizeof(G));
    66         int x, y;
    67         while (~scanf("%d%d", &x, &y)) addedge(x, y, 1);
    68         rep(i, 1, n1) addedge(s, i, 1);
    69         rep(i, n1 + 1, n) addedge(i, t, 1);
    70         int ans(0);
    71         while (bfs()) ans += dfs(s, 0x3f3f3f3f);
    72         printf("%d
    ", ans);
    73     }
    74     fclose(stdin);
    75     fclose(stdout);
    76     return 0;
    77 }
    View Code

        匈牙利:

     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 = 105;
    18 struct Ed {
    19     int u, v, nx, c; Ed() {}
    20     Ed(int _u, int _v, int _nx) :
    21         u(_u), v(_v), nx(_nx) {}
    22 } E[3005];
    23 int G[105], cnt;
    24 void addedge(int x, int y) {
    25     E[cnt] = Ed(x, y, G[x]);
    26     G[x] = cnt++;
    27 }
    28 
    29 bool used[maxn];
    30 int girl[maxn];
    31 bool find(int x) {
    32     for (int i = G[x]; i != -1; i = E[i].nx) {
    33         if (used[E[i].v]) continue;
    34         used[E[i].v] = 1;
    35         if (!girl[E[i].v] || find(girl[E[i].v])) {
    36             girl[E[i].v] = x;
    37             return true;
    38         }
    39     }
    40     return false;
    41 }
    42 int main() {
    43     freopen("flyer.in", "r", stdin);
    44     freopen("flyer.out", "w", stdout);
    45     int n, n1;
    46     while (~scanf("%d%d", &n, &n1)) {
    47         int x, y;
    48         memset(G, -1, sizeof(G));
    49         while (~scanf("%d%d", &x, &y)) {
    50             addedge(x, y);
    51         }
    52         clr(girl);
    53         int ans(0);
    54         rep(i, 1, n1) {
    55             clr(used);
    56             if (find(i)) ans++;
    57         }
    58         printf("%d
    ", ans);
    59     }
    60     
    61 }
    View Code

      网络流24题<2> COGS 727

        该问题的一般模型为最大权闭合图。

        [建模方法]

          把每个实验看作二分图X集合中的顶点,每个设备看作二分图Y集合中的顶点,增加源S和汇T。
          1、从S向每个Xi连接一条容量为该点收入的有向边。
          2、从Yi向T连接一条容量为该点支出的有向边。
          3、如果一个实验i需要设备j,连接一条从Xi到Yj容量为无穷大的有向边。

        用割来确定答案。

        设S-T割中的S割为选定的答案,A为实验集合,B为器材编号。

          ans:被选中的A集合中的顶点的权值 - 被选中的B集合中的顶点的权值

          Cut:没有被选中的A集合中的顶点的权值 + 被选中的B集合中的顶点的权值 + 被选中的A集合中与没有被选中的B集合中的边的Sum (一些inf的和)
          Total:所有A集合中的顶点的权值
          Total - Cut = ans
          最小割时没有Cut里的第三项,所以最小化Cut,最大流。

     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 = 0x3f3f3f3f;
    14 const i64 INF = ~0ULL>>1;
    15 //***************************
    16 
    17 const int maxn = 205;
    18 struct Ed {
    19     int u, v, nx, c; Ed() {}
    20     Ed(int _u, int _v, int _nx, int _c) :
    21         u(_u), v(_v), nx(_nx), c(_c) {}
    22 } E[10205];
    23 int G[maxn], cnt;
    24 void addedge(int x, int y, int v) {
    25     E[cnt] = Ed(x, y, G[x], v);
    26     G[x] = cnt++;
    27     E[cnt] = Ed(y, x, G[y], 0);
    28     G[y] = cnt++;
    29 }
    30 
    31 int s, t;
    32 int level[maxn];
    33 bool bfs() {
    34     static int que[maxn]; int qh(0), qt(0);
    35     clr(level);
    36     level[que[++qt] = s] = 1;
    37     while (qh != qt) {
    38         int x = que[++qh];
    39         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 
    40             level[que[++qt] = E[i].v] = level[x] + 1;
    41     }
    42     return !!level[t];
    43 }
    44 int dfs(int u, int rm) {
    45     if (u == t) return rm;
    46     int rm1 = rm;
    47     for (int i = G[u]; i != -1; i = E[i].nx) {
    48         if (E[i].c && level[E[i].v] == level[u] + 1) {
    49             int flow = dfs(E[i].v, min(rm, E[i].c));
    50             E[i].c -= flow, E[i ^ 1].c += flow;
    51             if ((rm -= flow) == 0) break;
    52         }
    53     }
    54     if (rm1 == rm) level[u] = 0;
    55     return rm1 - rm;
    56 }
    57 
    58 char ch[100005];
    59 int main() {
    60     freopen("shuttle.in", "r", stdin);
    61     freopen("shuttle.out", "w", stdout);
    62     int n, m;
    63     int tot(0);
    64     scanf("%d%d", &n, &m);
    65     memset(G, -1, sizeof(G));
    66     s = 0, t = n + m + 1;
    67     rep(i, 1, n) {
    68         int val;
    69         scanf("%d ", &val);
    70         tot += val;
    71         addedge(s, i, val);
    72         fgets(ch, 100000, stdin);
    73         int id(0);
    74         for (int j = 0; ch[j]; j++) {
    75             if (ch[j] == ' ' || ch[j] == '
    ' || ch[j] == '
    ') {
    76                 if (id) addedge(i, id + n, inf);
    77                 id = 0;
    78             }
    79             else {
    80                 id = id * 10 + ch[j] - '0';
    81             }
    82         }
    83     }
    84     rep(i, 1, m) {
    85         int val;
    86         scanf("%d", &val);
    87         addedge(n + i, t, val);
    88     }
    89     int ans(0);
    90     while (bfs()) ans += dfs(s, 0x3f3f3f3f);
    91     rep(i, 1, n) if (level[i]) printf("%d ", i);
    92     puts("");
    93     rep(i, 1, m) if (level[i + n]) printf("%d ", i);
    94     puts("");
    95     printf("%d
    ", tot - ans);
    96     return 0;
    97 }
    View Code

      网络流24题<3> COGS 728

        二分图最大匹配。假设一开始n个点自己是一条链,那么此时有n条链,假设可以匹配一个,那么路径数就会减一,所以跑出最大匹配即可。

        懒,只写了dinic:

      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 = 0x3f3f3f3f;
     14 const i64 INF = ~0ULL>>1;
     15 //***************************
     16 
     17 const int maxn = 305;
     18 
     19 struct Ed {
     20     int u, v, c, nx; Ed() {}
     21     Ed(int _u, int _v, int _c, int _nx) :
     22         u(_u), v(_v), c(_c), nx(_nx) {}
     23 } E[13005];
     24 int G[305], cnt;
     25 void addedge(int u, int v, int c) {
     26     E[cnt] = Ed(u, v, c, G[u]);
     27     G[u] = cnt++;
     28     E[cnt] = Ed(v, u, 0, G[v]);
     29     G[v] = cnt++;
     30 }
     31 
     32 int level[maxn];
     33 int s, t;
     34 bool bfs() {
     35     static int que[305]; int qh(0), qt(0);
     36     clr(level);
     37     level[que[++qt] = s] = 1;
     38     while (qh != qt) {
     39         int x = que[++qh];
     40         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
     41             level[que[++qt] = E[i].v] = level[x] + 1;
     42     }
     43     return !!level[t];
     44 }
     45 int dfs(int u, int rm) {
     46     if (u == t) return rm;
     47     int rm1 = rm;
     48     for (int i = G[u]; i != -1; i = E[i].nx) {
     49         if (E[i].c && level[E[i].v] == level[u] + 1) {
     50             int flow = dfs(E[i].v, min(rm, E[i].c));
     51             E[i].c -= flow, E[i ^ 1].c += flow;
     52             if ((rm -= flow) == 0) break;
     53         }
     54     }
     55     if (rm1 == rm) level[u] = 0;
     56     return rm1 - rm;
     57 }
     58 
     59 int main() {
     60     freopen("path3.in", "r", stdin);
     61     freopen("path3.out", "w", stdout);
     62     int n, m;
     63     scanf("%d%d", &n, &m);
     64     s = 0, t = (n << 1) + 1;
     65     memset(G, -1, sizeof(G));
     66     rep(i, 1, m) {
     67         int x, y;
     68         scanf("%d%d", &x, &y);
     69         addedge(x, y + n, 1);
     70     }
     71     rep(i, 1, n) {
     72         addedge(s, i, 1);
     73         addedge(i + n, t, 1);
     74     }
     75     while (bfs()) dfs(s, 0x3f3f3f3f);
     76     static int nxt[maxn], frm[maxn];
     77     rep(i, 1, n) {
     78         for (int j = G[i]; j != -1; j = E[j].nx) {
     79             if (E[j].v <= n) continue;
     80             if (E[j].c == 0) {
     81                 nxt[i] = E[j].v - n, frm[E[j].v - n] = i;
     82                 break;
     83             }
     84         }
     85     }
     86     int ans(0);
     87     rep(i, 1, n) {
     88         if (frm[i] == 0) {
     89             int k = i;
     90             while (k) {
     91                 printf("%d ", k);
     92                 k = nxt[k];
     93             }
     94             puts("");
     95             ans++;
     96         }
     97     }
     98     printf("%d
    ", ans);
     99     fclose(stdin);
    100     fclose(stdout);
    101     return 0;
    102 }
    View Code

        匈牙利算法请见友链中的Ngshily.   http://www.cnblogs.com/Ngshily/p/4988909.html

        

      bzoj 3996

        同类与网络流24题<2>,最大权闭合图。

        D =(A * B - C)* A^T;

        E = A * B;

        Eij = sigma(k = (1 ~ n)) Aik * Bkj;因为 E为[1,n]的矩阵 把Eij表示为Ej.

        Ej = sigma(k = (1 ~ n)) Ak * Bkj;

        设F = E * A^T;

        F(1, 1) = sigma(p = 1 ~n) Ep * Ap;

        代入得 F = sigma(p = 1 ~ n) (sigma(k = 1 ~ n) Ak * Bkp * Ap)

        

        G = C * A^T

        G = sigma(k, 1, n) Ck * Ak;

        由此可见,若要取得Bkp,则Ak和Ap必须为1,也就是Bij依赖Ai和Aj,后面的式子则是Ai的选取代价,所以得到了最大权闭合图的模型。

     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 = 0x3f3f3f3f;
    14 const i64 INF = ~0ULL>>1;
    15 //***************************
    16  
    17 const int maxn = 260005;
    18 const int maxm = 751005;
    19  
    20 struct Ed {
    21     int u, v, nx, c; Ed() {}
    22     Ed(int _u, int _v, int _nx, int _c) :
    23         u(_u), v(_v), nx(_nx), c(_c) {}
    24 } E[maxm << 1];
    25 int G[maxn], cnt;
    26 void addedge(int u, int v, int c) {
    27     E[cnt] = Ed(u, v, G[u], c);
    28     G[u] = cnt++;
    29     E[cnt] = Ed(v, u, G[v], 0);
    30     G[v] = cnt++;
    31 }
    32  
    33 int s, t;
    34 int level[maxn];
    35 bool bfs() {
    36     static int que[maxn]; int qh(0), qt(0);
    37     clr(level);
    38     level[que[++qt] = s] = 1;
    39     while (qh != qt) {
    40         int x = que[++qh];
    41         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
    42             level[que[++qt] = E[i].v] = level[x] + 1;
    43     }
    44     return !!level[t];
    45 }
    46 int dfs(int u, int rm) {
    47     if (u == t) return rm;
    48     int rm1 = rm;
    49     for (int i = G[u]; i != -1; i = E[i].nx) {
    50         if (E[i].c && level[E[i].v] == level[u] + 1) {
    51             int flow = dfs(E[i].v, min(E[i].c, rm));
    52             E[i].c -= flow, E[i ^ 1].c += flow;
    53             if ((rm -= flow) == 0) break;
    54         }
    55     }
    56     if (rm1 == rm) level[u] = 0;
    57     return rm1 - rm;
    58 }
    59  
    60 int main() {
    61     int n;
    62     scanf("%d", &n);
    63     s = 0, t = n * n + n + 1;
    64     memset(G, -1, sizeof(G));
    65     int tot(0);
    66     REP(i, 0, n) rep(j, 1, n) {
    67         int id;
    68         scanf("%d", &id);
    69         tot += id;
    70         addedge(s, i * n + j, id);
    71         addedge(i * n + j, i + n * n + 1, inf);
    72         addedge(i * n + j, j + n * n, inf);
    73     }
    74     rep(i, 1, n) {
    75         int id;
    76         scanf("%d", &id);
    77         addedge(n * n + i, t, id);
    78     }
    79     int ans(0);
    80     while (bfs()) ans += dfs(s, 0x3f3f3f3f);
    81     printf("%d
    ", tot - ans);
    82     return 0;
    83 }
    View Code

      

      网络流24题<5> COGS 729 圆桌问题

        类似于二分图匹配,给每个单位连他们人数的流量,每个单位依次给每个桌子连1的流量,每个桌子依次给超级汇点连桌子的容量的流量。

        dinic即可。

     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 = 0x3f3f3f3f;
    14 const i64 INF = ~0ULL>>1;
    15 //***************************
    16 
    17 const int maxn = 505;
    18 const int maxm = 41000;
    19 
    20 struct Ed {
    21     int u, v, nx, c; Ed() {}
    22     Ed(int _u, int _v, int _nx, int _c) :
    23         u(_u), v(_v), nx(_nx), c(_c) {}
    24 } E[maxm << 1];
    25 int G[maxn], cnt;
    26 void addedge(int u, int v, int c) {
    27     E[cnt] = Ed(u, v, G[u], c);
    28     G[u] = cnt++;
    29     E[cnt] = Ed(v, u, G[v], 0);
    30     G[v] = cnt++;
    31 }
    32 
    33 int s, t;
    34 int level[maxn];
    35 bool bfs() {
    36     static int que[maxn]; int qh(0), qt(0);
    37     clr(level);
    38     level[que[++qt] = s] = 1;
    39     while (qh != qt) {
    40         int x = que[++qh];
    41         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
    42             level[que[++qt] = E[i].v] = level[x] + 1;
    43     }
    44     return !!level[t];
    45 }
    46 int dfs(int u, int rm) {
    47     if (u == t) return rm;
    48     int rm1 = rm;
    49     for (int i = G[u]; i != -1; i = E[i].nx) {
    50         if (E[i].c && level[E[i].v] == level[u] + 1) {
    51             int flow = dfs(E[i].v, min(rm, E[i].c));
    52             E[i].c -= flow, E[i ^ 1].c += flow;
    53             if ((rm -= flow) == 0) break;
    54         }
    55     }
    56     if (rm1 == rm) level[u] = 0;
    57     return rm1 - rm;
    58 }
    59 
    60 int main() {
    61     freopen("roundtable.in", "r", stdin);
    62     freopen("roundtable.out", "w", stdout);
    63     int n, m;
    64     scanf("%d%d", &n, &m);
    65     s = 0, t = n + m + 1;
    66     memset(G, -1, sizeof(G));
    67     int tot(0);
    68     rep(i, 1, n) {
    69         int id;
    70         scanf("%d", &id);
    71         tot += id;
    72         addedge(s, i, id);
    73     }
    74     rep(i, 1, n) rep(j, 1, m) addedge(i, n + j, 1);
    75     rep(i, 1, m) {
    76         int id;
    77         scanf("%d", &id);
    78         addedge(n + i, t, id);
    79     }
    80     int ans(0);
    81     while (bfs()) ans += dfs(s, 0x3f3f3f3f);
    82     if (ans < tot) puts("0");
    83     else puts("1");
    84     static int sta[maxn];
    85     int top(0);
    86     rep(i, 1, n) {
    87         for (int j = G[i]; j != -1; j = E[j].nx) {
    88             if (E[j].c == 0) {
    89                 sta[++top] = E[j].v - n;
    90             }
    91         }
    92         drep(j, top, 1) printf("%d ", sta[j]);
    93         top = 0;
    94         puts("");
    95     }
    96     fclose(stdin);
    97     fclose(stdout);
    98     return 0;
    99 }
    View Code

    2015年11月24日

      网络流24题 COGS 魔术球问题

        最小路径覆盖问题。

        先二分答案,建图dinic即可,有一点需要注意,在连边时,i 只能向 i + 1 及其以后的边连边,否则不符合实际意义,也会使二分图满流。

     1 #include <bits/stdc++.h>
     2 #define rep(i, a, b) for (register 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 = 0x3f3f3f3f;
    14 const i64 INF = ~0ULL>>1;
    15 //***************************
    16 
    17 const int maxn = 3205;
    18 const int maxm = 38545;
    19 
    20 struct Ed {
    21     int u, v, nx, c; Ed() {}
    22     Ed(int _u, int _v, int _nx, int _c) :
    23         u(_u), v(_v), nx(_nx), c(_c) {}
    24 } E[maxm << 1];
    25 int G[maxn], cnt;
    26 void addedge(int u, int v, int c) {
    27     E[cnt] = Ed(u, v, G[u], c);
    28     G[u] = cnt++;
    29     E[cnt] = Ed(v, u, G[v], 0);
    30     G[v] = cnt++;
    31 }
    32 
    33 int level[maxn], s, t;
    34 bool bfs() {
    35     static int que[maxn]; int qh(0), qt(0);
    36     clr(level);
    37     level[que[++qt] = s] = 1;
    38     while (qh != qt) {
    39         int x = que[++qh];
    40         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
    41             level[que[++qt] = E[i].v] = level[x] + 1;
    42     }
    43     return !!level[t];
    44 }
    45 int dfs(int u, int rm) {
    46     if (u == t) return rm;
    47     int rm1 = rm;
    48     for (int i = G[u]; i != -1; i = E[i].nx) {
    49         if (E[i].c && level[E[i].v] == level[u] + 1) {
    50             int flow = dfs(E[i].v, min(E[i].c, rm));
    51             E[i].c -= flow, E[i ^ 1].c += flow;
    52             if ((rm -= flow) == 0) break;
    53         }
    54     }
    55     if (rm1 == rm) level[u] = 0;
    56     return rm1 - rm;
    57 }
    58 
    59 int main() {
    60     freopen("balla.in", "r", stdin);
    61     freopen("balla.out", "w", stdout);
    62     int sho;
    63     scanf("%d", &sho);
    64     int low = 0, high = 1605;
    65     while (low < high - 1) {
    66         int mid = low + high >> 1;
    67         s = 0, t = (mid << 1) + 1;
    68         memset(G, -1, sizeof(G)); cnt = 0;
    69         rep(i, 1, mid) rep(j, i + 1, mid) {
    70             int sq = sqrt(1.0 * i + j);
    71             if (sq * sq == i + j) addedge(i, mid + j, 1);
    72         }
    73         rep(i, 1, mid) addedge(s, i, 1), addedge(i + mid, t, 1);
    74         int ans(0);
    75         while (bfs()) ans += dfs(s, 0x3f3f3f3f);
    76         if (mid - ans <= sho) low = mid;
    77         else high = mid;
    78     }
    79     printf("%d
    ", low);
    80     fclose(stdin);
    81     fclose(stdout);
    82     return 0;
    83 }
    View Code

    2015年11月26日

      网络流24题 10 餐巾计划

        把每个点拆成两个点,一个是每天用掉的点,另一边为来源。

        从S到用掉的点连接费用为0,容量为ri的边。

        从来源的点向T连接费用为0,容量为ri的边。   来限制流量。

        在用掉的点的集合中,i 向 i + 1 连接费用为0,容量为inf的边。

        从S到来源集合中连接容量为inf,费用为P的边。

        连上快洗和慢洗。

        感觉第一个集合中的点中用作限制,第二个才是解决的方案。

        zkw费用流:

     1 #include <bits/stdc++.h>
     2 #define rep(i, a, b) for (int i = a; i <= b; i++)
     3 #define REP(i, a, b) for (int i = a; i < b; i++)
     4 #define drep(i, a, b) for (int i = a; i >= b; i--)
     5 #define clr(x) memset(x, 0, sizeof(x))
     6 #define pb push_back
     7 #define mp make_pair
     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 = 405, maxm = 40605;
    18 struct Ed {
    19     int u, v, nx, c, s; Ed() {};
    20     Ed (int _u, int _v, int _nx, int _c, int _s) :
    21         u(_u), v(_v), nx(_nx), c(_c), s(_s) {}
    22 } E[maxm << 1];
    23 int G[maxn], cnt;
    24 void addedge(int u, int v, int c, int s) {
    25     E[cnt] = Ed(u, v, G[u], c, s);
    26     G[u] = cnt++;
    27     E[cnt] = Ed(v, u, G[v], 0, -s);
    28     G[v] = cnt++;
    29 }
    30 
    31 int s, t;
    32 int dis[maxn], vis[maxn];
    33 bool spfa() {
    34     static int que[maxm]; int qh(0), qt(0);
    35     memset(dis, 0x3f, sizeof(dis));
    36     clr(vis);
    37     vis[que[++qt] = s] = 1; dis[s] = 0;
    38     while (qh != qt) {
    39         int x = que[++qh]; vis[x] = 0;
    40         for (int i = G[x]; i != -1; i = E[i].nx) {
    41             if (E[i].c && E[i].s + dis[x] < dis[E[i].v]) {
    42                 dis[E[i].v] = dis[x] + E[i].s;
    43                 if (!vis[E[i].v]) que[++qt] = E[i].v, vis[E[i].v] = 1;
    44             }
    45         }
    46     }
    47     return dis[t] != 0x3f3f3f3f;
    48 }
    49 
    50 int ans;
    51 int dfs(int u, int rm) {
    52     vis[u] = 1;
    53     if (u == t) return rm;
    54     int rm1 = rm;
    55     for (int i = G[u]; i != -1; i = E[i].nx) {
    56         if (dis[u] + E[i].s == dis[E[i].v] && E[i].c && !vis[E[i].v]) {
    57             int flow = dfs(E[i].v, min(rm, E[i].c));
    58             E[i].c -= flow, E[i ^ 1].c += flow;
    59             ans += flow * E[i].s;
    60             if ((rm -= flow) == 0) break;
    61         }
    62     }
    63     if (rm1 == rm) dis[u] = 0;
    64     return rm1 - rm;
    65 }
    66 
    67 int a[maxn];
    68 int main() {
    69     freopen("napkin.in", "r", stdin);
    70     freopen("napkin.out", "w", stdout);
    71     int n;
    72     scanf("%d", &n);
    73     rep(i, 1, n) scanf("%d", &a[i]);
    74     int P, M, F, N, S;
    75     scanf("%d%d%d%d%d", &P, &M, &F, &N, &S);
    76     memset(G, -1, sizeof(G)); s = 0, t = (n << 1) + 1;
    77     rep(i, 1, n) addedge(s, i, a[i], 0), addedge(s, n + i, inf, P), addedge(i + n, t, a[i], 0);
    78     REP(i, 1, n) addedge(i, i + 1, inf, 0);
    79     rep(i, 1, n) {
    80         if (i + M <= n) addedge(i, i + M + n, inf, F);
    81         if (i + N <= n) addedge(i, i + N + n, inf, S);
    82     }
    83 
    84     while (spfa()) clr(vis), dfs(s, 0x3f3f3f3f);
    85     printf("%d
    ", ans);
    86     fclose(stdin);
    87     fclose(stdout);
    88     return 0;
    89 }
    View Code

        普通费用流:

     1 #include <bits/stdc++.h>
     2 #define rep(i, a, b) for (int i = a; i <= b; i++)
     3 #define REP(i, a, b) for (int i = a; i < b; i++)
     4 #define drep(i, a, b) for (int i = a; i >= b; i--)
     5 #define pb push_back
     6 #define mp make_pair
     7 #define xx first
     8 #define yy second
     9 using namespace std;
    10 typedef long long i64;
    11 typedef pair<int, int> pii;
    12 const int inf = ~0U >> 1;
    13 const i64 INF = ~0ULL >> 1;
    14 //*****************************
    15 
    16 const int maxn = 405, maxm = 40605;
    17 struct Ed {
    18     int u, v, nx, c, s; Ed() {};
    19     Ed (int _u, int _v, int _nx, int _c, int _s) :
    20         u(_u), v(_v), nx(_nx), c(_c), s(_s) {}
    21 } E[maxm << 1];
    22 int G[maxn], cnt;
    23 void addedge(int u, int v, int c, int s) {
    24     E[cnt] = Ed(u, v, G[u], c, s);
    25     G[u] = cnt++;
    26     E[cnt] = Ed(v, u, G[v], 0, -s);
    27     G[v] = cnt++;
    28 }
    29 
    30 bool vis[maxn];
    31 int s, t;
    32 int pre[maxn];
    33 bool spfa() {
    34     static int que[maxm]; int qh(0), qt(0);
    35     static int dis[maxn];
    36     memset(dis, 0x3f, sizeof(dis));
    37     memset(vis, 0, sizeof(vis));
    38     vis[que[++qt] = s] = 1;
    39     dis[s] = 0;
    40     while (qh != qt) {
    41         int x = que[++qh];
    42         vis[x] = 0;
    43         for (int i = G[x]; i != -1; i = E[i].nx) {
    44             if (E[i].c && dis[x] + E[i].s < dis[E[i].v]) {
    45                 dis[E[i].v] = dis[x] + E[i].s;
    46                 pre[E[i].v] = i;
    47                 if (!vis[E[i].v]) {
    48                     vis[E[i].v] = 1;
    49                     que[++qt] = E[i].v;
    50                 }
    51             }
    52         }
    53     }
    54     if (dis[t] == 0x3f3f3f3f) return false;
    55     return true;
    56 }
    57 
    58 int a[maxn];
    59 int main() {
    60     freopen("napkin.in", "r", stdin);
    61     freopen("napkin.out", "w", stdout);
    62     int n;
    63     scanf("%d", &n);
    64     rep(i, 1, n) scanf("%d", &a[i]);
    65     int P, M, F, N, S;
    66     scanf("%d%d%d%d%d", &P, &M, &F, &N, &S);
    67 
    68     memset(G, -1, sizeof(G));
    69     s = 0, t = (n << 1) + 1;
    70     rep(i, 1, n) { addedge(s, i, a[i], 0); addedge(i + n, t, a[i], 0); }
    71     REP(i, 1, n) addedge(i, i + 1, inf, 0);
    72     rep(i, 1, n) addedge(s, i + n, inf, P);
    73     rep(i, 1, n) {
    74         if (i + M <= n) addedge(i, i + M + n, inf, F);
    75         if (i + N <= n) addedge(i, i + N + n, inf, S);
    76     }
    77     int ans(0);
    78     pre[s] = -1;
    79     while (spfa()) {
    80         int flow = inf;
    81         for (int i = pre[t]; i != -1; i = pre[E[i].u]) {
    82             flow = min(flow, E[i].c);
    83         }
    84         for (int i = pre[t]; i != -1; i = pre[E[i].u]) {
    85             E[i].c -= flow, E[i ^ 1].c += flow;
    86             ans += flow * E[i].s;
    87         }
    88     }
    89     printf("%d
    ", ans);
    90 }
    View Code

      网络流24题 11 航空路线问题

        可以dp多线程。

        同样,拆点,一个点为入点,一个为出点。

        S到1的入点连接 【容量为2,费用为1】的边,n的出点连接 【容量为2,费用为0】的边,每条航线连接【容量为1,费用为1】的边,每个点出点到自己的入点连接【容量为1,费用为0】的边。(和第一个点和最后一个点相连的边容量均为2)。

        如果最大流不够,-1。

        因为要求最大费用最大流,所以把边权建成-1就好。

      1 #include <bits/stdc++.h>
      2 #define rep(i, a, b) for (int i = a; i <= b; i++)
      3 #define REP(i, a, b) for (int i = a; i < b; i++)
      4 #define drep(i, a, b) for (int i = a; i >= b; i--)
      5 #define clr(x) memset(x, 0, sizeof(x))
      6 #define pb push_back
      7 #define mp make_pair
      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 = 205, maxm = 10005;
     18 struct Ed {
     19     int u, v, nx, c, s; Ed() {}
     20     Ed(int _u, int _v, int _nx, int _c, int _s) :
     21         u(_u), v(_v), nx(_nx), c(_c), s(_s) {}
     22 } E[maxm << 1];
     23 int G[maxn], cnt;
     24 void addedge(int u, int v, int c, int s) {
     25     E[cnt] = Ed(u, v, G[u], c, s);
     26     G[u] = cnt++;
     27     E[cnt] = Ed(v, u, G[v], 0, -s);
     28     G[v] = cnt++;
     29 }
     30  
     31 int s, t, pre[maxn];
     32 int vis[maxn], dis[maxn];
     33 bool spfa() {
     34     static int que[maxm]; int qh(0), qt(0);
     35     clr(vis), memset(dis, 0x3f, sizeof(dis));
     36     vis[que[++qt] = s] = 1, dis[s] = 0;
     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[x] + E[i].s < dis[E[i].v]) {
     41                 pre[E[i].v] = i;
     42                 dis[E[i].v] = dis[x] + E[i].s;
     43                 if (!vis[E[i].v]) vis[que[++qt] = E[i].v] = 1;
     44             }
     45         }
     46     }
     47     return dis[t] != 0x3f3f3f3f;
     48 }
     49  
     50 map <string, int> M;
     51 string ch[maxn];
     52 int main() {
     53     int n, m;
     54     string str;
     55     cin >> n >> m;
     56     rep(i, 1, n) {
     57         cin >> str;
     58         ch[i] = str;
     59         M[str] = i;
     60     }
     61     s = 0, t = (n << 1) + 1;
     62     memset(G, -1, sizeof(G));
     63     addedge(s, 1, 2, -1), addedge(n << 1, t, 2, 0);
     64     while (m--) {
     65         int x, y;
     66         cin >> str; x = M[str];
     67         cin >> str; y = M[str];
     68         if (x == 1 || y == n) addedge(x, y + n, 2, -1);
     69         else addedge(x, y + n, 1, -1);
     70     }
     71     REP(i, 2, n) addedge(i + n, i, 1, 0);
     72     addedge(1 + n, 1, 2, 0), addedge(n + n, n, 2, 0);
     73     pre[0] = -1;
     74     int ans(0), f(0);
     75     while (spfa()) {
     76         int flow = inf;
     77         for (int i = pre[t]; i != -1; i = pre[E[i].u])
     78             flow = min(flow, E[i].c);
     79         f += flow;
     80         for (int i = pre[t]; i != -1; i = pre[E[i].u]) {
     81             E[i].c -= flow, E[i ^ 1].c += flow;
     82             ans += E[i].s * flow;
     83         }
     84     }
     85     if (f < 2) puts("-1");
     86     else {
     87         static int pri[maxn]; int top(0);
     88         cout << -ans - 2 << endl;
     89         int k = 1;
     90         while (1) {
     91             pri[++top] = k;
     92             for (int i = G[k]; i != -1; i = E[i].nx) {
     93                 if (E[i].v - n <= k) continue;
     94                 if (E[i ^ 1].c != 0) {
     95                     E[i].c += 1, E[i ^ 1].c -= 1;
     96                     k = E[i].v - n;
     97                     break;
     98                 }
     99             }
    100             if (k == n) break;
    101         }
    102         k = n + n;
    103         while (1) {
    104             pri[++top] = k - n;
    105             for (int i = G[k]; i != -1; i = E[i].nx) {
    106                 if (E[i].v >= k - n) continue;
    107                 if (E[i].c != 0) {
    108                     k = E[i].v + n;
    109                     break;
    110                 }
    111             }
    112             if (k == n + 1) break;
    113         }
    114         pri[++top] = k - n;
    115         for (int i = top; i >= 1; i--) cout << ch[pri[i]] << endl;
    116     }
    117     return 0;
    118 }
    View Code
  • 相关阅读:
    python基础练习题(题目 画菱形)
    python基础练习题(题目 两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单)
    python基础练习题(题目 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少)
    python基础练习题(题目 一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程找出1000以内的所有完数)
    python基础练习题(题目 求s=a+aa+aaa+aaaa+aa…a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制)
    酒库重构测试—半自动化验证
    python基础练习题(题目 输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数)
    python基础练习题(题目 将一个整数分解质因数。例如:输入90,打印出90=2*3*3*5)
    python基础练习题(题目 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身)
    python基础练习题(题目 判断101-200之间有多少个素数,并输出所有素数。)
  • 原文地址:https://www.cnblogs.com/y7070/p/4988800.html
Copyright © 2020-2023  润新知