• HDU 2732:Leapin' Lizards(最大流)


    http://acm.hdu.edu.cn/showproblem.php?pid=2732

    题意:给出两个地图,蜥蜴从一个柱子跳跃到另外一个地方,那么这个柱子就可能会坍塌,第一个地图是柱子可以容忍跳跃多少次(即从它为起点可以跳跃多少次,然后坍塌),第二个地图是蜥蜴的位置。还有一个跳跃距离d,即蜥蜴可以跳跃不超过d的距离(曼哈顿距离),如果跳到地图外面,即蜥蜴逃跑成功,问最终留下的蜥蜴数最少是多少。

    思路:我觉得如果不是在做网络流套题应该想不到这是网络流。其实挺简单的建图。首先考虑蜥蜴的位置,和柱子的位置,如果柱子的位置有蜥蜴,那么这个柱子可以容忍的跳跃次数wi要-1,因为这个地方的蜥蜴必须跳走。然后把蜥蜴的位置,柱子的位置,和地图外边的位置存下来,蜥蜴和柱子拆点,形成一个S->lizard1->lizard2->pil1->pil2->out->T这样的网络。

    1、如果蜥蜴可以直接跳到地图外,那么可以在lizard2和out之间连一条边,如果柱子可以跳到地图外,就在pil2和out之间连边,权值都为INF。

    2、如果柱子之间如果距离在d之间,那么也可以连边,权值为将要跳到的柱子的wi。

    3、如果蜥蜴可以跳到柱子,那么可以连边,权值为柱子的wi。

    4、S和lizard1连边权值为1。

    5、out和T连边权值为INF。

    6、蜥蜴拆点权值为1,柱子拆点权值为wi。

    这样就做完了。注意输出要仔细。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 using namespace std;
     12 #define INF 0x3f3f3f3f
     13 #define N 100010
     14 typedef long long LL;
     15 struct Edge {
     16     int v, nxt, cap;
     17     Edge () {}
     18     Edge (int v, int cap, int nxt) : v(v), cap(cap), nxt(nxt) {}
     19 } edge[N];
     20 struct Node {
     21     int x, y;
     22     friend bool operator < (const Node &a, const Node &b) {
     23         return a.x < b.x;
     24     }
     25 } lizard[N], pil[N], out[N];
     26 int head[N], tot, cur[N], gap[N], pre[N], dis[N], w[N], S, T;
     27 
     28 void Add(int u, int v, int cap) {
     29     edge[tot] = Edge(v, cap, head[u]); head[u] = tot++;
     30     edge[tot] = Edge(u, 0, head[v]); head[v] = tot++;
     31 }
     32 
     33 int Cal(Node a, Node b) {
     34     return abs(a.x - b.x) + abs(a.y - b.y);
     35 }
     36 
     37 void BFS() {
     38     memset(dis, -1, sizeof(dis));
     39     memset(gap, 0, sizeof(gap));
     40     queue<int> que; que.push(T);
     41     dis[T] = 0; gap[0]++;
     42     while(!que.empty()) {
     43         int u = que.front(); que.pop();
     44         for(int i = head[u]; ~i; i = edge[i].nxt) {
     45             Edge& e = edge[i];
     46             if(~dis[e.v]) continue;
     47             dis[e.v] = dis[u] + 1;
     48             que.push(e.v);
     49             gap[dis[e.v]]++;
     50         }
     51     }
     52 }
     53 
     54 int ISAP(int n) {
     55     BFS();
     56     memcpy(cur, head, sizeof(cur));
     57     int ans = 0, i, u = pre[S] = S;
     58     while(dis[S] < n) {
     59         if(u == T) {
     60             int flow = INF, index;
     61             for(i = S; i != T; i = edge[cur[i]].v)
     62                 if(edge[cur[i]].cap < flow) flow = edge[cur[i]].cap, index = i;
     63             for(i = S; i != T; i = edge[cur[i]].v)
     64                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
     65             ans += flow; u = index;
     66         }
     67         for(i = cur[u]; ~i; i = edge[i].nxt)
     68             if(dis[edge[i].v] + 1 == dis[u] && edge[i].cap > 0) break;
     69         if(~i) {
     70             pre[edge[i].v] = u; cur[u] = i;
     71             u = edge[i].v;
     72         } else {
     73             if(--gap[dis[u]] == 0) break;
     74             int md = n;
     75             for(int i = head[u]; ~i; i = edge[i].nxt)
     76                 if(dis[edge[i].v] < md && edge[i].cap > 0)
     77                     md = dis[edge[i].v], cur[u] = i;
     78             gap[dis[u] = md + 1]++;
     79             u = pre[u];
     80         }
     81     }
     82     return ans;
     83 }
     84 
     85 int main() {
     86     int t, cas = 0;
     87     cin >> t;
     88     while(t--) {
     89         int n, d, m; char mp[50][50], s[50][50];
     90         scanf("%d%d", &n, &d);
     91         memset(head, -1, sizeof(head)); tot = 0;
     92         int lzcnt = 0, picnt = 0, oucnt = 0;
     93         for(int i = 1; i <= n; i++) scanf("%*c%s", mp[i] + 1);
     94         m = strlen(mp[1] + 1);
     95         for(int i = 1; i <= n; i++) {
     96             scanf("%*c%s", s[i] + 1);
     97             for(int j = 1; j <= m; j++) {
     98                 if(s[i][j] == 'L') {
     99                     lizard[++lzcnt].x = i, lizard[lzcnt].y = j;
    100                     if(mp[i][j] - '0' > 0) {
    101                         pil[++picnt].x = i, pil[picnt].y = j, w[picnt] = mp[i][j] - '0' - 1; // 如果柱子位置有蜥蜴,那么流量要-1
    102                     }
    103                 } else if(mp[i][j] != '0') {
    104                     pil[++picnt].x = i, pil[picnt].y = j, w[picnt] = mp[i][j] - '0';
    105                 }
    106             }
    107         }
    108         for(int i = 1; i <= n; i++) {
    109             out[++oucnt].x = i; out[oucnt].y = 0;
    110             out[++oucnt].x = i; out[oucnt].y = m + 1;
    111         }
    112         for(int i = 1; i <= m; i++) {
    113             out[++oucnt].x = 0; out[oucnt].y = i;
    114             out[++oucnt].x = n + 1; out[oucnt].y = i;
    115         }
    116         S = 0; T = 2 * lzcnt + 2 * picnt + oucnt + 1;
    117         for(int i = 1; i <= lzcnt; i++) Add(S, i, 1), Add(i, i + lzcnt, 1); // 源点和蜥蜴,蜥蜴拆点
    118         for(int i = 1; i <= oucnt; i++) Add(2 * lzcnt + 2 * picnt + i, T, INF); // 边界点和汇点
    119         for(int i = 1; i <= picnt; i++) Add(2 * lzcnt + i, 2 * lzcnt + picnt + i, w[i]); // 跳跃点拆点
    120         for(int i = 1; i <= lzcnt; i++) {
    121             for(int j = 1; j <= picnt; j++) {
    122                 if(Cal(lizard[i], pil[j]) <= d && Cal(lizard[i], pil[j]) != 0) {
    123                     Add(i + lzcnt, j + 2 * lzcnt, w[j]); // 蜥蜴的第二个点和跳跃点第一个点
    124                 }
    125             }
    126             for(int j = 1; j <= oucnt; j++) {
    127                 if(Cal(lizard[i], out[j]) <= d) Add(i + lzcnt, j + lzcnt * 2 + picnt * 2, INF);
    128             }
    129         }
    130         for(int i = 1; i <= picnt; i++) {
    131             for(int j = i + 1; j <= picnt; j++) {
    132                 if(Cal(pil[i], pil[j]) <= d) {
    133                     Add(i + 2 * lzcnt + picnt, j + 2 * lzcnt, INF); // 跳跃点
    134                     Add(j + 2 * lzcnt + picnt, i + 2 * lzcnt, INF);
    135                 }
    136             }
    137             for(int j = 1; j <= oucnt; j++) {
    138                 if(Cal(pil[i], out[j]) <= d) Add(i + lzcnt * 2 + picnt, j + lzcnt * 2 + picnt * 2, INF);
    139             }
    140         }
    141         int ans = lzcnt - ISAP(T + 1);
    142         printf("Case #%d: ", ++cas);
    143         if(ans < 2) {
    144             if(ans <= 0) printf("no lizard was ");
    145             else printf("1 lizard was ");
    146         } else {
    147             printf("%d lizards were ", ans);
    148         }
    149         puts("left behind.");
    150     }
    151     return 0;
    152 }

     #看了一下别人的思路,一开始自己也想的差不多那样,但是硬是调不出来,就用了这么复杂方法,觉得自己没救了,好简单的思路。

    S->pil1->pil2->T,如果柱子上有蜥蜴就将这个点和S连,如果在该柱子可以跳出去,那么就将这个点和T相连,然后和能够相连的柱子连边就好了。再写一遍

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 using namespace std;
     12 #define INF 0x3f3f3f3f
     13 #define N 100010
     14 typedef long long LL;
     15 struct Edge {
     16     int v, nxt, cap;
     17     Edge () {}
     18     Edge (int v, int cap, int nxt) : v(v), cap(cap), nxt(nxt) {}
     19 } edge[N];
     20 struct Node {
     21     int x, y, w, flag;
     22 } pil[N];
     23 int head[N], tot, cur[N], gap[N], pre[N], dis[N], S, T;
     24 
     25 void Add(int u, int v, int cap) {
     26     edge[tot] = Edge(v, cap, head[u]); head[u] = tot++;
     27     edge[tot] = Edge(u, 0, head[v]); head[v] = tot++;
     28 }
     29 
     30 int Cal(Node a, Node b) {
     31     return abs(a.x - b.x) + abs(a.y - b.y);
     32 }
     33 
     34 void BFS() {
     35     memset(dis, -1, sizeof(dis));
     36     memset(gap, 0, sizeof(gap));
     37     queue<int> que; que.push(T);
     38     dis[T] = 0; gap[0]++;
     39     while(!que.empty()) {
     40         int u = que.front(); que.pop();
     41         for(int i = head[u]; ~i; i = edge[i].nxt) {
     42             Edge& e = edge[i];
     43             if(~dis[e.v]) continue;
     44             dis[e.v] = dis[u] + 1;
     45             que.push(e.v);
     46             gap[dis[e.v]]++;
     47         }
     48     }
     49 }
     50 
     51 int ISAP(int n) {
     52     BFS();
     53     memcpy(cur, head, sizeof(cur));
     54     int ans = 0, i, u = pre[S] = S;
     55     while(dis[S] < n) {
     56         if(u == T) {
     57             int flow = INF, index;
     58             for(i = S; i != T; i = edge[cur[i]].v)
     59                 if(edge[cur[i]].cap < flow) flow = edge[cur[i]].cap, index = i;
     60             for(i = S; i != T; i = edge[cur[i]].v)
     61                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
     62             ans += flow; u = index;
     63         }
     64         for(i = cur[u]; ~i; i = edge[i].nxt)
     65             if(dis[edge[i].v] + 1 == dis[u] && edge[i].cap > 0) break;
     66         if(~i) {
     67             pre[edge[i].v] = u; cur[u] = i;
     68             u = edge[i].v;
     69         } else {
     70             if(--gap[dis[u]] == 0) break;
     71             int md = n;
     72             for(int i = head[u]; ~i; i = edge[i].nxt)
     73                 if(dis[edge[i].v] < md && edge[i].cap > 0)
     74                     md = dis[edge[i].v], cur[u] = i;
     75             gap[dis[u] = md + 1]++;
     76             u = pre[u];
     77         }
     78     }
     79     return ans;
     80 }
     81 
     82 int main() {
     83     int t, cas = 0;
     84     cin >> t;
     85     while(t--) {
     86         int n, d, m; char mp[50][50], s[50][50];
     87         scanf("%d%d", &n, &d);
     88         memset(head, -1, sizeof(head)); tot = 0;
     89         int cnt = 0, tol = 0;
     90         for(int i = 1; i <= n; i++) {
     91             scanf("%s", s[i] + 1);
     92             m = strlen(s[i] + 1);
     93             for(int j = 1; j <= m; j++)
     94                 if(s[i][j] != '0') pil[++cnt].x = i, pil[cnt].y = j, pil[cnt].w = s[i][j] - '0';
     95         }
     96         for(int i = 1; i <= n; i++) {
     97             scanf("%s", mp[i] + 1);
     98             for(int j = 1; j <= m; j++) {
     99                 for(int k = 1; k <= cnt; k++) {
    100                     if(pil[k].x == i && pil[k].y == j) {
    101                         if(mp[i][j] == 'L') pil[k].flag = 1, tol++;
    102                         else pil[k].flag = 0;
    103                         break;
    104                     }
    105                 }
    106             }
    107         }
    108         S = 0, T = 2 * cnt + 1;
    109         for(int i = 1; i <= cnt; i++) {
    110             Add(i, i + cnt, pil[i].w);
    111             if(pil[i].flag == 1) Add(S, i, 1);
    112             for(int j = i + 1; j <= cnt; j++) {
    113                 if(Cal(pil[i], pil[j]) <= d) {
    114                     Add(i + cnt, j, INF);
    115                     Add(j + cnt, i, INF);
    116                 }
    117             }
    118             if(pil[i].x <= d || pil[i].y <= d || n - pil[i].x < d || m - pil[i].y < d)
    119                 Add(i + cnt, T, INF);
    120         }
    121 
    122         int ans = tol - ISAP(T + 1);
    123         printf("Case #%d: ", ++cas);
    124         if(ans < 2) {
    125             if(ans <= 0) printf("no lizard was ");
    126             else printf("1 lizard was ");
    127         } else {
    128             printf("%d lizards were ", ans);
    129         }
    130         puts("left behind.");
    131     }
    132     return 0;
    133 }
  • 相关阅读:
    kafka搭建
    kafaka学习笔记
    metastore 简单说明
    二 python并发编程之多进程-理论
    文件指针偏移量
    FTP
    1 并发编程
    操作系统简介
    1 网络编程
    网络编程-osi七层
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6241298.html
Copyright © 2020-2023  润新知