• 网络流24题


    骑士共存问题

    按马的轨迹连边,最后是一张二分图,求最大匹配。可以跑匈牙利直接求出来,也可以连源点和汇点跑Dinic。

    我是学二分图的时候写的,当时写的是匈牙利。我当时码风好奇怪

     1 #include <bits/stdc++.h>
     2 #define ID(x, y) (x - 1) * n + y
     3 #define New(p) p = &tmp[++ecnt]
     4 
     5 struct Edge {int to; Edge *nxt;} tmp[1000005], *head[40005];
     6 
     7 int vis[40005], match[40005], ecnt = -1, n, m, tim, ans, tot;
     8 int dx[] = {-1, -2, 1, 2, -1, -2, 1, 2}, dy[]={-2, -1, -2, -1, 2, 1, 2, 1};
     9 bool ban[205][205];
    10 
    11 inline void Add(int f, int to) {Edge *p; New(p); p -> to = to, p -> nxt = head[f], head[f] = p;}
    12 
    13 bool dfs(int x) {
    14     for (Edge *i = head[x]; i != NULL; i = i -> nxt) {
    15         if (vis[i -> to] != tim) {
    16             vis[i -> to] = tim;
    17             if (!match[i -> to] || dfs(match[i -> to])) {
    18                 match[i -> to] = x;
    19                 return 1;
    20             }
    21         }
    22     }
    23     return 0;
    24 }
    25 
    26 signed main() {
    27     scanf("%d%d", &n, &m);
    28     for (int i = 1, x, y; i <= m; i++) {
    29         scanf("%d%d", &x, &y);
    30         ban[x][y] = 1;
    31     }
    32     for (int i = 1; i <= n; i++) {
    33         for (int j = 1; j <= n; j++) {
    34             if(ban[i][j] || ((i + j) & 1)) continue;
    35             for (int k = 0; k < 8; k++) {
    36                 int x = i + dx[k], y = j + dy[k];
    37                 if (ban[x][y] || x < 1 || x > n || y < 1 || y > n) continue;
    38                 Add(ID(i, j), ID(x, y));
    39             }
    40         }
    41     }
    42     for (int i = 1; i <= n; i++) {
    43         for (int j = 1; j <= n; j++) {
    44             if (!ban[i][j]) {
    45                 ++tim;
    46                 ++tot;
    47                 if (dfs(ID(i, j))) ++ans;
    48             }
    49         }
    50     }
    51     printf("%d
    ", tot - ans);
    52     return 0;
    53 }
    匈牙利

    飞行员配对方案问题

    按给定关系建图,仍是二分图,求最大匹配。

    依旧写的是匈牙利。我当时没看见SPJ,写了一堆奇怪的东西。。。。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 
     5 namespace Gekoo {
     6     struct Edge {
     7         int to, nxt;
     8     }e[N];
     9 
    10     pair<int, int> p[N];
    11 
    12     int m, n, head[N], ecnt, match[N], ans, pcnt;
    13     bool vis[N];
    14 
    15     void AddEdge(int f, int to) {
    16         e[++ecnt].to = to;
    17         e[ecnt].nxt = head[f];
    18         head[f] = ecnt;
    19     }
    20 
    21     bool dfs(int u) {
    22         for (int i = head[u]; i; i = e[i].nxt) {
    23             int v = e[i].to;
    24             if (!vis[v]) {
    25                 vis[v] = 1;
    26                 if (!match[v] || dfs(match[v])) {
    27                     match[v] = u;
    28                     return 1;
    29                 }
    30             }
    31         }
    32         return 0;
    33     }
    34 
    35     void QAQ() {
    36         scanf("%d%d", &m, &n);
    37         int i, j;
    38         while (1) {
    39             scanf("%d%d", &i, &j);
    40             if (i == -1 && j == -1) break;
    41             else AddEdge(i, j);
    42         }
    43         for (int i = 1; i <= m; i++) {
    44             memset(vis, 0, sizeof(vis));
    45             if(dfs(i)) ans++;
    46         }
    47         if (ans == 0) {
    48             puts("No Solution!");
    49             return ;
    50         } else {
    51             printf("%d
    ", ans);
    52             for (int i = m + 1; i <= n; i++) {
    53                 if (match[i]) {
    54                     p[++pcnt] = make_pair(match[i], i);
    55                 }
    56             }
    57             sort(p + 1, p + 1 + pcnt);
    58             for (int i = 1; i <= pcnt; i++) {
    59                 printf("%d %d
    ", p[i].first, p[i].second);
    60             }
    61             return ;
    62         }
    63     }
    64 }
    65 
    66 signed main() {
    67     Gekoo::QAQ();
    68     return 0;
    69 }
    又是匈牙利

    方格取数问题

    把图按格子奇偶性黑白染色,源点连黑色,白色连汇点,黑色向相邻白点连,求出最小割,用数字和减去。

    建出来的仍是二分图,这个过程其实就是在求二分图的最大独立集。

     1 #include <bits/stdc++.h>
     2 #define id(x, y) ((x - 1) * m + y) 
     3 
     4 const int N = 500005, INF = 0x3f3f3f3f;
     5 const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
     6 int n, m, sum, ecnt = 1, S, T;
     7 int matrix[105][105], head[N], dep[N];
     8 struct Edge {
     9     int to, nxt, val;
    10 } e[N << 5];
    11 
    12 inline void addEdge(int f, int to, int val) {
    13     e[++ecnt] = {to, head[f], val}, head[f] = ecnt;
    14     e[++ecnt] = {f, head[to], 0}, head[to] = ecnt;
    15 }
    16 
    17 bool bfs() {
    18     memset(dep, 0, sizeof(dep));
    19     dep[S] = 1;
    20     std::queue<int> q;
    21     q.push(S);
    22     while (!q.empty()) {
    23         int x = q.front();
    24         q.pop();
    25         for (int i = head[x], y = e[i].to; i; i = e[i].nxt, y = e[i].to) {
    26             if (!dep[y] && e[i].val) {
    27                 dep[y] = dep[x] + 1;
    28                 if (y == T) return true;
    29                 q.push(y);
    30             }
    31         }
    32     }
    33     return false;
    34 }
    35 
    36 int dfs(int x, int flow) {
    37     if (x == T) return flow;
    38     int las = flow, q;
    39     for (int i = head[x], y = e[i].to; i; i = e[i].nxt, y = e[i].to) {
    40         if (dep[y] == dep[x] + 1 && e[i].val && las) {
    41             q = dfs(y, std::min(e[i].val, las));
    42             if (!q) {dep[y] = 0; continue;}
    43             las -= q, e[i].val -= q, e[i^1].val += q;
    44         }
    45     }
    46     return flow - las;
    47 }
    48 
    49 int dinic() {
    50     int maxflow = 0;
    51     while (bfs()) maxflow += dfs(S, INF);
    52     return maxflow;
    53 }
    54 
    55 signed main() {
    56     scanf("%d%d", &n, &m);
    57     for (int i = 1; i <= n; i++) {
    58         for (int j = 1; j <= m; j++) {
    59             scanf("%d", &matrix[i][j]);
    60             sum += matrix[i][j];
    61         }
    62     }
    63     S = n * m  + 1, T = S + 1;
    64     for (int i = 1; i <= n; i++) {
    65         for (int j = 1; j <= m; j++) {
    66             if ((i + j) & 1) {
    67                 addEdge(S, id(i, j), matrix[i][j]);
    68                 for (int k = 0; k <= 3; k++) {
    69                     int xx = i + dx[k], yy = j + dy[k];
    70                     if (xx < 1 || yy < 1 || xx > n || yy > m) continue;
    71                     addEdge(id(i, j), id(xx, yy), INF);
    72                 }
    73             } else {
    74                 addEdge(id(i, j), T, matrix[i][j]);
    75             }
    76         }
    77     }
    78     printf("%d
    ", sum - dinic());
    79     return 0;
    80 }
    这次是Dinic了
  • 相关阅读:
    webpack-dev-server 源码
    2021前端会有什么新的变化
    父类 超类 基类 子类 派生类
    Java的权限修饰符(public,private,protected,默认friendly)
    class修饰符public、private、protected、static、abstract
    hash和签名 、证书
    前端加密解密crypto
    appid app_key app_secret
    sdk开发 、sdk与插件的区别
    CF76C
  • 原文地址:https://www.cnblogs.com/gekoo/p/11342641.html
Copyright © 2020-2023  润新知