• FZU 1844 Earthquake Damage(最大流最小割)


    Problem Description

    Open Source Tools help earthquake researchers stay a step ahead. Many geological research facilities around the world use or are in the process of developing open source software and applications designed to interpret and share information with other researchers. For example, OpenSees is an open source software framework for developing apps that help understand what happens to structures during and after earthquakes to help engineers design stronger buildings. Researchers are also using OpenSees to understand the potential ill-effects of seismic activity on viaducts and bridges.

    China has had an earthquake that has struck Sichuan Province on Monday 12 May 2008!

    The earthquake has damaged some of the cities so that they are unpassable. Remarkably, after repairing by Chinese People's Liberation Army, all the driveways between cities were fixed.

    As usual, Sichuan Province is modeled as a set of P (1 <= P <= 3,000) cities conveniently numbered 1..P which are connected by a set of C (1 <= C <= 20,000) non-directional driveways conveniently numbered 1..C. Driveway i connects city a_i and b_i (1 <= a_i <= P; 1 <= b_i <= P). Driveway might connect a_i to itself or perhaps might connect two cities more than once. The Crisis Center is located in city 1.

    A total of N (1 <= N <= P) survivors (in different cities) sequentially contacts Crisis Center via moobile phone with an integer message report_j (2 <= report_j <= P) that indicates that city report_j is undamaged but that the calling survivor is unable to return to the Crisis Center from city report_j because he/she could not find a path that does not go through damaged city.

    After all the survivors report in, determine the minimum number of cities that are damaged.

     Input

    Input consists of several testcases. The format of each case as follow:

    • Line 1: Three space-separated integers: P, C, and N
    • Lines 2..C+1: Line i+1 describes cowpath i with two integers: a_i and b_i
    • Lines C+2..C+N+1: Line C+1+j contains a single integer: report_j

     Output

    For each testcase, output a line with one number, the minimum number of damaged cities.

    用最大流最小割定理,最大流=最小割,很久以前做的,题目已忘,我是来放模版的

    DINIC算法+当前弧优化+有容量上限,78MS

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 using namespace std;
      5 
      6 #define MAXN 6010
      7 #define MAXM 100010
      8 
      9 #define INF 0x7fffffff
     10 
     11 struct Dinic {
     12     int n, m, st, ed, ecnt;
     13     int vis[MAXN], head[MAXN];
     14     int cur[MAXN], d[MAXN];
     15     int to[MAXM], next[MAXM], flow[MAXM], cap[MAXM];
     16 
     17     void init(int ss, int tt){
     18         memset(head,0,sizeof(head));
     19         ecnt = 2;
     20         st = ss; ed = tt;
     21     }
     22 
     23     void addEdge(int u,int v,int c) {
     24         //flow[ecnt] = c
     25         to[ecnt] = v; cap[ecnt] = c; flow[ecnt] = 0; next[ecnt] = head[u]; head[u] = ecnt++;
     26         to[ecnt] = u; cap[ecnt] = 0; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
     27     }
     28 
     29     bool bfs() {
     30         memset(vis, 0, sizeof(vis));
     31         queue<int> que; que.push(st);
     32         d[st] = 0; vis[st] = true;
     33         while(!que.empty()){
     34             int u = que.front(); que.pop();
     35             for(int p = head[u]; p; p = next[p]){
     36                 int v = to[p];
     37                 if (!vis[v] && cap[p] > flow[p]){//flow[p] > 0
     38                     vis[v] = 1;
     39                     d[v] = d[u] + 1;
     40                     que.push(v);
     41                     if(v == ed) return true;
     42                 }
     43             }
     44         }
     45         return vis[ed];
     46     }
     47 
     48     int dfs(int u, int a) {
     49         if(u == ed || a == 0) return a;
     50         int outflow = 0, f;
     51         for(int &p = cur[u]; p; p = next[p]){
     52             int v = to[p];
     53             if(d[u] + 1 == d[v] && (f = dfs(v, min(a, cap[p] - flow[p]))) > 0){//min(a, flow[p])
     54                 flow[p] += f;//flow[p] -= f;
     55                 flow[p ^ 1] -= f;//flow[p ^ 1] += f;
     56                 outflow += f;
     57                 a -= f;
     58                 if(a == 0) break;
     59             }
     60         }
     61         return outflow;
     62     }
     63 
     64     int Maxflow() {
     65         int ans = 0;
     66         while(bfs()){
     67             for(int i = 0; i <= ed; ++i) cur[i] = head[i];
     68             ans += dfs(st, INF);
     69         }
     70         return ans;
     71     }
     72 } G;
     73 
     74 int vis[MAXN];
     75 
     76 int main() {
     77     int ss, tt, N, C, P;
     78     while(scanf("%d%d%d",&P,&C,&N)!=EOF){
     79         ss = 1; tt = 2*P+1;
     80         G.init(ss, tt);
     81         while(C--){
     82             int a, b;
     83             scanf("%d%d",&a,&b);
     84             G.addEdge(a + P, b, INF);
     85             G.addEdge(b + P, a, INF);
     86         }
     87         memset(vis, 0, sizeof(vis));
     88         while(N--){
     89             int x;
     90             scanf("%d",&x);
     91             G.addEdge(x, tt, INF);
     92             vis[x] = 1;
     93         }
     94         for(int i = 1; i <= P; ++i){
     95             if(i != 1 && !vis[i]) G.addEdge(i, i + P, 1);
     96             else G.addEdge(i, i + P, INF);
     97         }
     98         G.n = tt;
     99         printf("%d
    ",G.Maxflow());
    100     }
    101     return 0;
    102 }
    View Code

    DINIC算法+当前弧优化+只有余量,62MS

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 using namespace std;
      5 
      6 #define MAXN 6010
      7 #define MAXM 100010
      8 
      9 #define INF 0x7fffffff
     10 
     11 struct Dinic {
     12     int n, m, st, ed, ecnt;
     13     int vis[MAXN], head[MAXN];
     14     int cur[MAXN], d[MAXN];
     15     int to[MAXM], next[MAXM], flow[MAXM];
     16 
     17     void init(int ss, int tt){
     18         memset(head,0,sizeof(head));
     19         ecnt = 2;
     20         st = ss; ed = tt;
     21     }
     22 
     23     void addEdge(int u,int v,int f) {
     24         to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
     25         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
     26     }
     27 
     28     bool bfs() {
     29         memset(vis, 0, sizeof(vis));
     30         queue<int> que; que.push(st);
     31         d[st] = 0; vis[st] = true;
     32         while(!que.empty()){
     33             int u = que.front(); que.pop();
     34             for(int p = head[u]; p; p = next[p]){
     35                 int v = to[p];
     36                 if (!vis[v] && flow[p] > 0){
     37                     vis[v] = 1;
     38                     d[v] = d[u] + 1;
     39                     que.push(v);
     40                     if(v == ed) return true;
     41                 }
     42             }
     43         }
     44         return vis[ed];
     45     }
     46 
     47     int dfs(int u, int a) {
     48         if(u == ed || a == 0) return a;
     49         int outflow = 0, f;
     50         for(int &p = cur[u]; p; p = next[p]){
     51             int v = to[p];
     52             if(d[u] + 1 == d[v] && (f = dfs(v, min(a, flow[p]))) > 0){
     53                 flow[p] -= f;
     54                 flow[p ^ 1] += f;
     55                 outflow += f;
     56                 a -= f;
     57                 if(a == 0) break;
     58             }
     59         }
     60         return outflow;
     61     }
     62 
     63     int Maxflow() {
     64         int ans = 0;
     65         while(bfs()){
     66             for(int i = 0; i <= ed; ++i) cur[i] = head[i];
     67             ans += dfs(st, INF);
     68         }
     69         return ans;
     70     }
     71 } G;
     72 
     73 int vis[MAXN];
     74 
     75 int main() {
     76     int ss, tt, N, C, P;
     77     while(scanf("%d%d%d",&P,&C,&N)!=EOF){
     78         ss = 1; tt = 2*P+1;
     79         G.init(ss, tt);
     80         while(C--){
     81             int a, b;
     82             scanf("%d%d",&a,&b);
     83             G.addEdge(a + P, b, INF);
     84             G.addEdge(b + P, a, INF);
     85         }
     86         memset(vis, 0, sizeof(vis));
     87         while(N--){
     88             int x;
     89             scanf("%d",&x);
     90             G.addEdge(x, tt, INF);
     91             vis[x] = 1;
     92         }
     93         for(int i = 1; i <= P; ++i){
     94             if(i != 1 && !vis[i]) G.addEdge(i, i + P, 1);
     95             else G.addEdge(i, i + P, INF);
     96         }
     97         G.n = tt;
     98         printf("%d
    ",G.Maxflow());
     99     }
    100     return 0;
    101 }
    View Code

    ISAP算法,78MS(把注释删掉再交一次又变成了93MS,OJ的时间果然信不过o(╯□╰)o)//不能有点0

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <queue>
      5 using namespace std;
      6 
      7 #define MAXN 6010
      8 #define MAXM 100010
      9 #define INF 0x7fffffff
     10 
     11 struct SAP {
     12     int vis[MAXN], head[MAXN];
     13     int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
     14     int to[MAXM], flow[MAXM], next[MAXM];
     15     int ecnt, st, ed;
     16 
     17     void init(int ss, int tt) {
     18         memset(head, 0, sizeof(head));
     19         ecnt = 2;
     20         st = ss; ed = tt;
     21     }
     22 
     23     void addEdge(int u,int v,int f) {
     24         to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
     25         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
     26     }
     27 
     28     int Max_flow() {
     29         int ans = 0, minFlow = INF, n = ed, u;
     30         for (int i = 0; i <= n; ++i){
     31             cur[i] = head[i];
     32             gap[i] = dis[i] = 0;
     33         }
     34         u = pre[st] = st;
     35         gap[0] = n;
     36         while (dis[st] < n){
     37             bool flag = false;
     38             for (int &p = cur[u]; p; p = next[p]){
     39                 int v = to[p];
     40                 if (flow[p] > 0 && dis[u] == dis[v] + 1){
     41                     flag = true;
     42                     minFlow = min(minFlow, flow[p]);
     43                     pre[v] = u;
     44                     u = v;
     45                     if(u == ed){
     46                         ans += minFlow;
     47                         while (u != st){
     48                             u = pre[u];
     49                             flow[cur[u]] -= minFlow;
     50                             flow[cur[u] ^ 1] += minFlow;
     51                         }
     52                         minFlow = INF;
     53                     }
     54                     break;
     55                 }
     56             }
     57             if (flag) continue;
     58             int minDis = n-1;
     59             for (int p = head[u]; p; p = next[p]){
     60                 int v = to[p];
     61                 if (flow[p] && dis[v] < minDis){
     62                     minDis = dis[v];
     63                     cur[u] = p;
     64                 }
     65             }
     66             if (--gap[dis[u]] == 0) break;
     67             gap[dis[u] = minDis+1]++;
     68             u = pre[u];
     69         }
     70         return ans;
     71     }
     72 } G;
     73 
     74 bool vis[MAXN];
     75 
     76 int main() {
     77     int ss, tt, N, C, P;
     78     while(scanf("%d%d%d",&P,&C,&N)!=EOF) {
     79         ss = 1; tt = 2*P+1;
     80         G.init(ss, tt);
     81         while(C--) {
     82             int a, b;
     83             scanf("%d%d",&a,&b);
     84             G.addEdge(a + P, b, INF);
     85             G.addEdge(b + P, a, INF);
     86         }
     87         memset(vis, 0, sizeof(vis));
     88         while(N--) {
     89             int x;
     90             scanf("%d",&x);
     91             G.addEdge(x, tt, INF);
     92             vis[x] = 1;
     93         }
     94         for(int i = 1; i <= P; ++i) {
     95             if(i != 1 && !vis[i]) G.addEdge(i, i + P, 1);
     96             else G.addEdge(i, i + P, INF);
     97         }
     98         printf("%d
    ",G.Max_flow());
     99     }
    100     return 0;
    101 }
    View Code

    ISAP算法+BFS初始化,62MS(SGU 438把我这模板跑跪了,现在换掉了>_<)//不能有点0

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <queue>
      5 using namespace std;
      6 
      7 #define MAXN 6010
      8 #define MAXM 100010
      9 #define INF 0x7fffffff
     10 
     11 struct SAP {
     12     int head[MAXN];
     13     int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
     14     int to[MAXM], flow[MAXM], next[MAXM];
     15     int ecnt, st, ed, n;
     16 
     17     void init(int ss, int tt, int nn) {
     18         memset(head, 0, sizeof(head));
     19         ecnt = 2;
     20         st = ss; ed = tt; n = nn;
     21     }
     22 
     23     void addEdge(int u,int v,int f) {
     24         to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
     25         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
     26     }
     27 
     28     void bfs() {
     29         memset(dis, 0x3f, sizeof(dis));
     30         queue<int> que; que.push(ed);
     31         dis[ed] = 0;
     32         while(!que.empty()) {
     33             int u = que.front(); que.pop();
     34             ++gap[dis[u]];
     35             for(int p = head[u]; p; p = next[p]) {
     36                 int v = to[p];
     37                 if (dis[v] > ed && flow[p ^ 1] > 0) {
     38                     dis[v] = dis[u] + 1;
     39                     que.push(v);
     40                 }
     41             }
     42         }
     43     }
     44 
     45     int Max_flow() {
     46         int ans = 0, minFlow = INF, u;
     47         for (int i = 0; i <= n; ++i){
     48             cur[i] = head[i];
     49             gap[i] = dis[i] = 0;
     50         }
     51         u = pre[st] = st;
     52         //gap[0] = n;
     53         bfs();
     54         while (dis[st] < n){
     55             bool flag = false;
     56             for (int &p = cur[u]; p; p = next[p]){
     57                 int v = to[p];
     58                 if (flow[p] > 0 && dis[u] == dis[v] + 1){
     59                     flag = true;
     60                     minFlow = min(minFlow, flow[p]);
     61                     pre[v] = u;
     62                     u = v;
     63                     if(u == ed){
     64                         ans += minFlow;
     65                         while (u != st){
     66                             u = pre[u];
     67                             flow[cur[u]] -= minFlow;
     68                             flow[cur[u] ^ 1] += minFlow;
     69                         }
     70                         minFlow = INF;
     71                     }
     72                     break;
     73                 }
     74             }
     75             if (flag) continue;
     76             int minDis = n-1;
     77             for (int p = head[u]; p; p = next[p]){
     78                 int v = to[p];
     79                 if (flow[p] && dis[v] < minDis){
     80                     minDis = dis[v];
     81                     cur[u] = p;
     82                 }
     83             }
     84             if (--gap[dis[u]] == 0) break;
     85             gap[dis[u] = minDis+1]++;
     86             u = pre[u];
     87         }
     88         return ans;
     89     }
     90 } G;
     91 
     92 bool vis[MAXN];
     93 
     94 int main() {
     95     int ss, tt, N, C, P;
     96     while(scanf("%d%d%d",&P,&C,&N)!=EOF) {
     97         ss = 1; tt = 2*P+1;
     98         G.init(ss, tt, tt);
     99         while(C--) {
    100             int a, b;
    101             scanf("%d%d",&a,&b);
    102             G.addEdge(a + P, b, INF);
    103             G.addEdge(b + P, a, INF);
    104         }
    105         memset(vis, 0, sizeof(vis));
    106         while(N--) {
    107             int x;
    108             scanf("%d",&x);
    109             G.addEdge(x, tt, INF);
    110             vis[x] = 1;
    111         }
    112         for(int i = 1; i <= P; ++i) {
    113             if(i != 1 && !vis[i]) G.addEdge(i, i + P, 1);
    114             else G.addEdge(i, i + P, INF);
    115         }
    116         printf("%d
    ",G.Max_flow());
    117     }
    118     return 0;
    119 }
    View Code
  • 相关阅读:
    第二十八节:Asp.Net Core中JWT的几种写法和认证方式
    第二十七节:安全存储机密程序
    第二十六节:扩展如何在控制台中使用HttpClientFactory、读取配置文件、数据保护、注入类
    第二十五节:数据保护程序和Hash的最佳实现(彩虹表原理)
    第二十四节:编码、解码、加密算法概念及实现(Base64、MD5、SHA、HMAC、DES、AES、RSA)
    第二十三节:Asp.Net Core中的几种安全防护
    第二十二节:Asp.Net Core中Https协议的相关配置
    第二十一节:Asp.Net Core中使用托管服务实现后台任务
    第X节:抢红包算法分享
    第四节:Geo类型介绍以及Redis批量操作、事务、分布式锁
  • 原文地址:https://www.cnblogs.com/oyking/p/3204522.html
Copyright © 2020-2023  润新知