• 线性规划与网络流24题


    诈个尸。

    1.飞行员配对方案问题

    二分图匹配。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 const int INF = 1e9;
      8 const int maxn = 2e5 + 10;
      9 int lv[maxn], it[maxn];
     10 int cnt, h[maxn];
     11 
     12 struct edge
     13 {
     14     int to, pre, cap;
     15 } e[maxn<<1];
     16 
     17 void init()
     18 {
     19     memset(h, -1, sizeof(h));
     20     cnt = 0;
     21 }
     22 
     23 void add(int from, int to, int cap)
     24 {
     25     e[cnt].pre = h[from];
     26     e[cnt].to = to;
     27     e[cnt].cap = cap;
     28     h[from] = cnt;
     29     cnt++;
     30 }
     31 
     32 void ad(int from, int to, int cap)
     33 {
     34     add(from, to, cap);
     35     add(to, from, 0);
     36 }
     37 
     38 void bfs(int s)
     39 {
     40     memset(lv, -1, sizeof(lv));
     41     queue<int> q;
     42     lv[s] = 0;
     43     q.push(s);
     44     while(!q.empty())
     45     {
     46         int v = q.front(); q.pop();
     47         for(int i = h[v]; i >= 0; i = e[i].pre)
     48         {
     49             int cap = e[i].cap, to = e[i].to;
     50             if(cap > 0 && lv[to] < 0)
     51             {
     52                 lv[to] = lv[v] + 1;
     53                 q.push(to);
     54             }
     55         }
     56     }
     57 }
     58 
     59 int dfs(int v, int t, int f)
     60 {
     61     if(v == t) return f;
     62     for(int &i = it[v]; i >= 0; i = e[i].pre)
     63     {
     64         int &cap = e[i].cap, to = e[i].to;
     65         if(cap > 0 && lv[v] < lv[to])
     66         {
     67             int d = dfs(to, t, min(f, cap));
     68             if(d > 0)
     69             {
     70                 cap -= d;
     71                 e[i^1].cap += d;
     72                 return d;
     73             }
     74         }
     75     }
     76     return 0;
     77 }
     78 
     79 int Dinic(int s, int t)
     80 {
     81     int flow = 0;
     82     while(1)
     83     {
     84         bfs(s);
     85         if(lv[t] < 0) return flow;
     86         memcpy(it, h, sizeof(it));
     87         int f;
     88         while((f = dfs(s, t, INF)) > 0) flow += f;
     89     }
     90 }
     91 
     92 int main(void)
     93 {
     94     init();
     95     int m, n;
     96     scanf("%d %d", &m, &n);
     97     while(1)
     98     {
     99         int u, v;
    100         scanf("%d %d", &u, &v);
    101         if(u == -1) break;
    102         ad(u, v, 1);
    103     }
    104     int S = n + 1, T = S + 1;
    105     for(int i = 1; i <= m; i++) ad(S, i, 1);
    106     for(int i = m + 1; i <= n; i++) ad(i, T, 1);
    107     int ans = Dinic(S, T);
    108     if(!ans) puts("No Solution!");
    109     else
    110     {
    111         printf("%d
    ", ans);
    112         for(int i = 1; i <= m; i++)
    113             for(int j = h[i]; j != -1; j = e[j].pre)
    114                 if(e[j].to <= n && !e[j].cap) printf("%d %d
    ", i, e[j].to);
    115     }
    116     return 0;
    117 }
    Aguin

    2.太空飞行计划问题

    最大权闭合图转最大流。

    见《最小割模型在信息学竞赛中的应用》。

    同时注意割边必满流,满流不一定是割边。

    但是Dinic找割点是很方便的,看lv就好。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <vector>
      7 using namespace std;
      8 const int INF = 1e9;
      9 const int maxn = 2e5 + 10;
     10 int lv[maxn], it[maxn];
     11 int cnt, h[maxn];
     12 vector<int> E, I;
     13 
     14 struct edge
     15 {
     16     int to, pre, cap;
     17 } e[maxn<<1];
     18 
     19 void init()
     20 {
     21     memset(h, -1, sizeof(h));
     22     cnt = 0;
     23 }
     24 
     25 void add(int from, int to, int cap)
     26 {
     27     e[cnt].pre = h[from];
     28     e[cnt].to = to;
     29     e[cnt].cap = cap;
     30     h[from] = cnt;
     31     cnt++;
     32 }
     33 
     34 void ad(int from, int to, int cap)
     35 {
     36     add(from, to, cap);
     37     add(to, from, 0);
     38 }
     39 
     40 void bfs(int s)
     41 {
     42     memset(lv, -1, sizeof(lv));
     43     queue<int> q;
     44     lv[s] = 0;
     45     q.push(s);
     46     while(!q.empty())
     47     {
     48         int v = q.front(); q.pop();
     49         for(int i = h[v]; i >= 0; i = e[i].pre)
     50         {
     51             int cap = e[i].cap, to = e[i].to;
     52             if(cap > 0 && lv[to] < 0)
     53             {
     54                 lv[to] = lv[v] + 1;
     55                 q.push(to);
     56             }
     57         }
     58     }
     59 }
     60 
     61 int dfs(int v, int t, int f)
     62 {
     63     if(v == t) return f;
     64     for(int &i = it[v]; i >= 0; i = e[i].pre)
     65     {
     66         int &cap = e[i].cap, to = e[i].to;
     67         if(cap > 0 && lv[v] < lv[to])
     68         {
     69             int d = dfs(to, t, min(f, cap));
     70             if(d > 0)
     71             {
     72                 cap -= d;
     73                 e[i^1].cap += d;
     74                 return d;
     75             }
     76         }
     77     }
     78     return 0;
     79 }
     80 
     81 int Dinic(int s, int t)
     82 {
     83     int flow = 0;
     84     while(1)
     85     {
     86         bfs(s);
     87         if(lv[t] < 0) return flow;
     88         memcpy(it, h, sizeof(it));
     89         int f;
     90         while((f = dfs(s, t, INF)) > 0) flow += f;
     91     }
     92 }
     93 
     94 int main(void)
     95 {
     96     init();
     97     int m, n, tot = 0;
     98     scanf("%d %d", &m, &n);
     99     int S = m + n + 1, T = S + 1;
    100     for(int i = 1; i <= m; i++)
    101     {
    102         int p, x;
    103         scanf("%d", &p);
    104         tot += p;
    105         ad(S, i, p);
    106         while(getchar() == ' ')
    107         {
    108             scanf("%d", &x);
    109             ad(i, x + m, INF);
    110         }
    111     }
    112     for(int i = 1; i <= n; i++)
    113     {
    114         int c;
    115         scanf("%d", &c);
    116         ad(i + m, T, c);
    117     }
    118     int ans = tot - Dinic(S, T);
    119     for(int i = 1; i <= m; i++) if(lv[i] != -1) printf("%d ", i); puts("");
    120     for(int i = 1; i <= n; i++) if(lv[i+m] != -1) printf("%d ", i); puts("");
    121     printf("%d
    ", ans);
    122     return 0;
    123 }
    Aguin

    3.最小路径覆盖问题

    DAG上最小路径覆盖转二分图匹配。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 const int INF = 1e9;
      8 const int maxn = 2e5 + 10;
      9 int lv[maxn], it[maxn];
     10 int cnt, h[maxn];
     11 int n, m;
     12 
     13 struct edge
     14 {
     15     int to, pre, cap;
     16 } e[maxn<<1];
     17 
     18 void init()
     19 {
     20     memset(h, -1, sizeof(h));
     21     cnt = 0;
     22 }
     23 
     24 void add(int from, int to, int cap)
     25 {
     26     e[cnt].pre = h[from];
     27     e[cnt].to = to;
     28     e[cnt].cap = cap;
     29     h[from] = cnt;
     30     cnt++;
     31 }
     32 
     33 void ad(int from, int to, int cap)
     34 {
     35     add(from, to, cap);
     36     add(to, from, 0);
     37 }
     38 
     39 void bfs(int s)
     40 {
     41     memset(lv, -1, sizeof(lv));
     42     queue<int> q;
     43     lv[s] = 0;
     44     q.push(s);
     45     while(!q.empty())
     46     {
     47         int v = q.front(); q.pop();
     48         for(int i = h[v]; i >= 0; i = e[i].pre)
     49         {
     50             int cap = e[i].cap, to = e[i].to;
     51             if(cap > 0 && lv[to] < 0)
     52             {
     53                 lv[to] = lv[v] + 1;
     54                 q.push(to);
     55             }
     56         }
     57     }
     58 }
     59 
     60 int dfs(int v, int t, int f)
     61 {
     62     if(v == t) return f;
     63     for(int &i = it[v]; i >= 0; i = e[i].pre)
     64     {
     65         int &cap = e[i].cap, to = e[i].to;
     66         if(cap > 0 && lv[v] < lv[to])
     67         {
     68             int d = dfs(to, t, min(f, cap));
     69             if(d > 0)
     70             {
     71                 cap -= d;
     72                 e[i^1].cap += d;
     73                 return d;
     74             }
     75         }
     76     }
     77     return 0;
     78 }
     79 
     80 int Dinic(int s, int t)
     81 {
     82     int flow = 0;
     83     while(1)
     84     {
     85         bfs(s);
     86         if(lv[t] < 0) return flow;
     87         memcpy(it, h, sizeof(it));
     88         int f;
     89         while((f = dfs(s, t, INF)) > 0) flow += f;
     90     }
     91 }
     92 
     93 void ans_print(int x)
     94 {
     95     printf("%d ", x);
     96     for(int i = h[x]; i >= 0; i = e[i].pre)
     97         if(!e[i].cap && e[i].to <= n + n)
     98             ans_print(e[i].to - n);
     99 }
    100 
    101 int main(void)
    102 {
    103     init();
    104     scanf("%d %d", &n, &m);
    105     int S = n + n + 1, T = S + 1;
    106     for(int i = 1; i <= n; i++) ad(S, i, 1), ad(n + i, T, 1);
    107     for(int i = 0; i < m; i++)
    108     {
    109         int u, v;
    110         scanf("%d %d", &u, &v);
    111         ad(u, v + n, 1);
    112     }
    113     int ans = n - Dinic(S, T);
    114     for(int i = h[T]; i >= 0; i = e[i].pre)
    115     {
    116         if(e[i].cap) continue;
    117         ans_print(e[i].to - n), puts("");
    118     }
    119     printf("%d
    ", ans);
    120     return 0;
    121 }
    Aguin

    4.魔术球问题

    转最小路径覆盖问题。(然而上界不是很好估计,大概不是很大。

    如果二分,每次要重建图,所以不如枚举快。

    枚举每次加边继续Dinic就可以了。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <vector>
      7 using namespace std;
      8 const int INF = 1e9;
      9 const int maxn = 2e4 + 10;
     10 const int maxm = 2e5;
     11 const int m = 1e4;
     12 int lv[maxn], it[maxn];
     13 int cnt, h[maxn];
     14 vector<int> is;
     15 
     16 struct edge
     17 {
     18     int to, pre, cap;
     19 } e[maxm<<1];
     20 
     21 void init()
     22 {
     23     memset(h, -1, sizeof(h));
     24     cnt = 0;
     25 }
     26 
     27 void add(int from, int to, int cap)
     28 {
     29     e[cnt].pre = h[from];
     30     e[cnt].to = to;
     31     e[cnt].cap = cap;
     32     h[from] = cnt;
     33     cnt++;
     34 }
     35 
     36 void ad(int from, int to, int cap)
     37 {
     38     add(from, to, cap);
     39     add(to, from, 0);
     40 }
     41 
     42 void bfs(int s)
     43 {
     44     memset(lv, -1, sizeof(lv));
     45     queue<int> q;
     46     lv[s] = 0;
     47     q.push(s);
     48     while(!q.empty())
     49     {
     50         int v = q.front(); q.pop();
     51         for(int i = h[v]; i >= 0; i = e[i].pre)
     52         {
     53             int cap = e[i].cap, to = e[i].to;
     54             if(cap > 0 && lv[to] < 0)
     55             {
     56                 lv[to] = lv[v] + 1;
     57                 q.push(to);
     58             }
     59         }
     60     }
     61 }
     62 
     63 int dfs(int v, int t, int f)
     64 {
     65     if(v == t) return f;
     66     for(int &i = it[v]; i >= 0; i = e[i].pre)
     67     {
     68         int &cap = e[i].cap, to = e[i].to;
     69         if(cap > 0 && lv[v] < lv[to])
     70         {
     71             int d = dfs(to, t, min(f, cap));
     72             if(d > 0)
     73             {
     74                 cap -= d;
     75                 e[i^1].cap += d;
     76                 return d;
     77             }
     78         }
     79     }
     80     return 0;
     81 }
     82 
     83 int Dinic(int s, int t)
     84 {
     85     int flow = 0;
     86     while(1)
     87     {
     88         bfs(s);
     89         if(lv[t] < 0) return flow;
     90         memcpy(it, h, sizeof(it));
     91         int f;
     92         while((f = dfs(s, t, INF)) > 0) flow += f;
     93     }
     94 }
     95 
     96 void ans_print(int x)
     97 {
     98     printf("%d ", x);
     99     for(int i = h[x]; i >= 0; i = e[i].pre)
    100         if(!e[i].cap && e[i].to <= m + m)
    101             ans_print(e[i].to - m);
    102 }
    103 
    104 int main(void)
    105 {
    106     for(int i = 1; i * i < maxn; i++) is.push_back(i * i);
    107     init();
    108     int n, ans = 0;
    109     scanf("%d", &n);
    110     int S = m + m + 1, T = S + 1;
    111     for(int i = 1; ; i++)
    112     {
    113         ad(S, i, 1), ad(i + m, T, 1);
    114         for(int j = 0; is[j] < i + i; j++)
    115             if(is[j] > i) ad(is[j] - i, i + m, 1);
    116         ans += Dinic(S, T);
    117         if(i - ans > n) {ans = i - 1; break;}
    118     }
    119     init();
    120     for(int i = 1; i <= ans; i++)
    121     {
    122         ad(S, i, 1), ad(i + m, T, 1);
    123         for(int j = 0; is[j] < i + i; j++)
    124             if(is[j] > i) ad(is[j] - i, i + m, 1);
    125     }
    126     Dinic(S, T);
    127     printf("%d
    ", ans);
    128     for(int i = h[T]; i >= 0; i = e[i].pre)
    129     {
    130         if(e[i].cap) continue;
    131         ans_print(e[i].to - m), puts("");
    132     }
    133     return 0;
    134 }
    Aguin

    5.圆桌问题

    二分图匹配。多case哇。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 const int INF = 1e9;
      8 const int maxn = 2e5 + 10;
      9 int lv[maxn], it[maxn];
     10 int cnt, h[maxn];
     11 
     12 struct edge
     13 {
     14     int to, pre, cap;
     15 } e[maxn<<1];
     16 
     17 void init()
     18 {
     19     memset(h, -1, sizeof(h));
     20     cnt = 0;
     21 }
     22 
     23 void add(int from, int to, int cap)
     24 {
     25     e[cnt].pre = h[from];
     26     e[cnt].to = to;
     27     e[cnt].cap = cap;
     28     h[from] = cnt;
     29     cnt++;
     30 }
     31 
     32 void ad(int from, int to, int cap)
     33 {
     34     add(from, to, cap);
     35     add(to, from, 0);
     36 }
     37 
     38 void bfs(int s)
     39 {
     40     memset(lv, -1, sizeof(lv));
     41     queue<int> q;
     42     lv[s] = 0;
     43     q.push(s);
     44     while(!q.empty())
     45     {
     46         int v = q.front(); q.pop();
     47         for(int i = h[v]; i >= 0; i = e[i].pre)
     48         {
     49             int cap = e[i].cap, to = e[i].to;
     50             if(cap > 0 && lv[to] < 0)
     51             {
     52                 lv[to] = lv[v] + 1;
     53                 q.push(to);
     54             }
     55         }
     56     }
     57 }
     58 
     59 int dfs(int v, int t, int f)
     60 {
     61     if(v == t) return f;
     62     for(int &i = it[v]; i >= 0; i = e[i].pre)
     63     {
     64         int &cap = e[i].cap, to = e[i].to;
     65         if(cap > 0 && lv[v] < lv[to])
     66         {
     67             int d = dfs(to, t, min(f, cap));
     68             if(d > 0)
     69             {
     70                 cap -= d;
     71                 e[i^1].cap += d;
     72                 return d;
     73             }
     74         }
     75     }
     76     return 0;
     77 }
     78 
     79 int Dinic(int s, int t)
     80 {
     81     int flow = 0;
     82     while(1)
     83     {
     84         bfs(s);
     85         if(lv[t] < 0) return flow;
     86         memcpy(it, h, sizeof(it));
     87         int f;
     88         while((f = dfs(s, t, INF)) > 0) flow += f;
     89     }
     90 }
     91 
     92 int main(void)
     93 {
     94     int N, M;
     95     scanf("%d %d", &N, &M);
     96     init();
     97     int sum = 0;
     98     int S = N + M + 1, T = S + 1;
     99     for(int i = 1; i <= N; i++)
    100     {
    101         int cap;
    102         scanf("%d", &cap);
    103         sum += cap;
    104         ad(S, i, cap);
    105     }
    106     for(int i = 1; i <= M; i++)
    107     {
    108         int cap;
    109         scanf("%d", &cap);
    110         ad(i + N, T, cap);
    111     }
    112     for(int i = 1; i <= N; i++)
    113         for(int j = 1; j <= M; j++)
    114             ad(i, j + N, 1);
    115     if(Dinic(S, T) == sum)
    116     {
    117         puts("1");
    118         for(int i = 1; i <= N; i++)
    119         {
    120             int fst = 1;
    121             for(int j = h[i]; j >= 0; j = e[j].pre)
    122             {
    123                 if(e[j].to != S && e[j].cap == 0)
    124                 {
    125                     if(fst) printf("%d", e[j].to - N);
    126                     else printf(" %d", e[j].to - N);
    127                     fst = 0;
    128                 }
    129             }
    130             puts("");
    131         }
    132     }
    133     else puts("0");
    134     return 0;
    135 }
    Aguin

    6.最长递增子序列问题

    第一问随便搞。后面拆点限流跑跑。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 const int INF = 1e9;
      8 const int maxn = 2e5 + 10;
      9 int lv[maxn], it[maxn];
     10 int cnt, h[maxn];
     11 
     12 struct edge
     13 {
     14     int to, pre, cap;
     15 } e[maxn<<1];
     16 
     17 void init()
     18 {
     19     memset(h, -1, sizeof(h));
     20     cnt = 0;
     21 }
     22 
     23 void add(int from, int to, int cap)
     24 {
     25     e[cnt].pre = h[from];
     26     e[cnt].to = to;
     27     e[cnt].cap = cap;
     28     h[from] = cnt;
     29     cnt++;
     30 }
     31 
     32 void ad(int from, int to, int cap)
     33 {
     34     add(from, to, cap);
     35     add(to, from, 0);
     36 }
     37 
     38 void bfs(int s)
     39 {
     40     memset(lv, -1, sizeof(lv));
     41     queue<int> q;
     42     lv[s] = 0;
     43     q.push(s);
     44     while(!q.empty())
     45     {
     46         int v = q.front(); q.pop();
     47         for(int i = h[v]; i >= 0; i = e[i].pre)
     48         {
     49             int cap = e[i].cap, to = e[i].to;
     50             if(cap > 0 && lv[to] < 0)
     51             {
     52                 lv[to] = lv[v] + 1;
     53                 q.push(to);
     54             }
     55         }
     56     }
     57 }
     58 
     59 int dfs(int v, int t, int f)
     60 {
     61     if(v == t) return f;
     62     for(int &i = it[v]; i >= 0; i = e[i].pre)
     63     {
     64         int &cap = e[i].cap, to = e[i].to;
     65         if(cap > 0 && lv[v] < lv[to])
     66         {
     67             int d = dfs(to, t, min(f, cap));
     68             if(d > 0)
     69             {
     70                 cap -= d;
     71                 e[i^1].cap += d;
     72                 return d;
     73             }
     74         }
     75     }
     76     return 0;
     77 }
     78 
     79 int Dinic(int s, int t)
     80 {
     81     int flow = 0;
     82     while(1)
     83     {
     84         bfs(s);
     85         if(lv[t] < 0) return flow;
     86         memcpy(it, h, sizeof(it));
     87         int f;
     88         while((f = dfs(s, t, INF)) > 0) flow += f;
     89     }
     90 }
     91 
     92 int a[444], dp[444];
     93 int main(void)
     94 {
     95     int n, s = 0;
     96     scanf("%d", &n);
     97     int S = 2 * n + 1, T = S + 1;
     98     for(int i = 1; i <= n; i++)
     99     {
    100         scanf("%d", a + i);
    101         dp[i] = 1;
    102         for(int j = 1; j < i; j++)
    103             if(a[i] > a[j]) dp[i] = max(dp[i], dp[j] + 1);
    104         s = max(s, dp[i]);
    105     }
    106 
    107     printf("%d
    ", s);
    108 
    109     init();
    110     for(int i = 1; i <= n; i++)
    111     {
    112         ad(i, i + n, 1);
    113 
    114         if(dp[i] == 1) ad(S, i, 1);
    115         if(dp[i] == s) ad(i + n, T, 1);
    116 
    117         for(int j = 1; j <= i; j++)
    118             if(a[j] < a[i] && dp[j] + 1 == dp[i]) ad(j + n, i, 1);
    119     }
    120 
    121     int ans = Dinic(S, T);
    122     printf("%d
    ", ans);
    123 
    124     ad(1, 1 + n, INF);
    125     ad(n, n + n, INF);
    126     ad(S, 1, INF);
    127     if(dp[n] == s) ad(n + n, T, INF);
    128 
    129     printf("%d
    ", ans + Dinic(S, T));
    130 
    131     return 0;
    132 }
    Aguin
  • 相关阅读:
    F
    E
    D
    B
    A
    C
    I
    G
    F
    架构sass文件
  • 原文地址:https://www.cnblogs.com/Aguin/p/5396674.html
Copyright © 2020-2023  润新知