zoukankan      html  css  js  c++  java
  • hlg1512March of the Penguins【无向图+拆点】

    March of the Penguins
    Time Limit: 2000 MS Memory Limit: 65535 K
    Total Submit: 14(7 users) Total Accepted: 9(6 users) Rating:  Special Judge: No
    Description

       Somewhere near the south pole, a number of penguins are standing on a number of ice floes. Being social animals, the penguins would like to get together, all on the same floe. The penguins do not want to get wet, so they have use their limited jump distance to get together by jumping from piece to piece. However, temperatures have been high lately, and the floes are showing cracks, and they get damaged further by the force needed to jump to another floe.

        Fortunately the penguins are real experts on cracking ice floes, and know exactly how many times a penguin can jump off each floe before it disintegrates and disappears. Landing on an ice floe does not damage it. You have to help the penguins find all floes where they can meet.

    Input
    On the first line one positive number: the number of testcases, at most 100. After that per
    testcase:
    • One line with the integer N(1≤N≤100) and a floating-point number D(0 ≤ D ≤ 100000), denoting the number of ice pieces and the maximum distance a penguin can jump.
    • N lines, each line containing xi, yi, ni and mi, denoting for each ice piece its X and Y coordinate, the number of penguins on it and the maximum number of times a penguin can jump off this piece before it disappears (−10 000≤xi, yi ≤10 000, 0≤ni ≤10,1≤mi ≤200).
    Output
    Per testcase:
    • One line containing a space-separated list of 0-based indices of the pieces on which all
    penguins can meet. If no such piece exists, output a line with the single number −1.
    Sample Input
    2
    5 3.5
    1 1 1 1
    2 3 0 1
    3 5 1 1
    5 1 1 1
    5 4 0 1
    3 1.1
    -1 0 5 10
    0 0 3 9
    2 0 1 1
    Sample Output
    1 2 4
    -1
    Source
    NWERC2007

    大意:有n块冰块,每块冰块上有一定数量企鹅,并且有一定的跳跃次数(jump off)超过这个次数冰块就会碎掉

    告诉每块冰块的企鹅数目和跳跃次数,问那些冰块能使所有的企鹅都到达(冰块编号从零开始)

    模型:

    1、首先这是一个无向图, 所以冰块之间建立路径的时候要件两条路

    2、节点有权值(跳跃次数) 所以要拆点

    思路:

    冰块拆点之间的权值是跳跃次数

    若两冰块之间能到达则建立两条路径(s1,t1)(s2,t2)的话  则由t1指向s2 由t2指向s1,权值为无穷

    超级源点跟每块冰块的s建立一条路径,权值为企鹅数量

    最后依次枚举每个点做汇点的最大流是否等于企鹅数量即可

    代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <vector>
      5 #include <queue>
      6 #include <cmath>
      7 using namespace std;
      8 
      9 const int maxn = 505;
     10 const int INF = 10000000;
     11 
     12 struct Point{
     13     int x, y, ni, mi;
     14 }point[maxn];
     15 
     16 
     17 struct Edge
     18 {
     19     int from, to, cap, flow, flow2;
     20 };
     21 
     22 struct ISAP {
     23   int n, m, s, t;
     24   vector<Edge> edges;
     25   vector<int> G[maxn];
     26   bool vis[maxn];
     27   int d[maxn];
     28   int cur[maxn];
     29   int p[maxn];
     30   int num[maxn];
     31 
     32   void AddEdge(int from, int to, int cap) {
     33     edges.push_back((Edge){from, to, cap, 0, 0});
     34     edges.push_back((Edge){to, from, 0, 0, 0});
     35     m = edges.size();
     36     G[from].push_back(m-2);
     37     G[to].push_back(m-1);
     38   }
     39 
     40   void init() {
     41     for(int i = 0; i < m; i++){
     42         edges[i].flow = edges[i].flow2;
     43     }
     44   }
     45 
     46   bool BFS() {
     47     memset(vis, 0, sizeof(vis));
     48     queue<int> Q;
     49     Q.push(t);
     50     vis[t] = 1;
     51     d[t] = 0;
     52     while(!Q.empty()) {
     53       int x = Q.front(); Q.pop();
     54       for(int i = 0; i < G[x].size(); i++) {
     55         Edge& e = edges[G[x][i]^1];
     56         if(!vis[e.from] && e.cap > e.flow) {
     57           vis[e.from] = 1;
     58           d[e.from] = d[x] + 1;
     59           Q.push(e.from);
     60         }
     61       }
     62     }
     63     return vis[s];
     64   }
     65 
     66   void ClearAll(int n) {
     67     this->n = n;
     68     for(int i = 0; i < n; i++) G[i].clear();
     69     edges.clear();
     70   }
     71 
     72   int Augment() {
     73     int x = t, a = INF;
     74     while(x != s) {
     75       Edge& e = edges[p[x]];
     76       a = min(a, e.cap-e.flow);
     77       x = edges[p[x]].from;
     78     }
     79     x = t;
     80     while(x != s) {
     81       edges[p[x]].flow += a;
     82       edges[p[x]^1].flow -= a;
     83       x = edges[p[x]].from;
     84     }
     85     return a;
     86   }
     87 
     88   int MaxFlow(int s, int t, int need) {
     89     this->s = s; this->t = t;
     90     int flow = 0;
     91     BFS();
     92     memset(num, 0, sizeof(num));
     93     for(int i = 0; i < n; i++) num[d[i]]++;
     94     int x = s;
     95     memset(cur, 0, sizeof(cur));
     96     while(d[s] < n) {
     97       if(x == t) {
     98         flow += Augment();
     99         if(flow >= need) return flow;
    100         x = s;
    101       }
    102       int ok = 0;
    103       for(int i = cur[x]; i < G[x].size(); i++) {
    104         Edge& e = edges[G[x][i]];
    105         if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance
    106           ok = 1;
    107           p[e.to] = G[x][i];
    108           cur[x] = i;
    109           x = e.to;
    110           break;
    111         }
    112       }
    113       if(!ok) {
    114         int m = n-1;
    115         for(int i = 0; i < G[x].size(); i++) {
    116           Edge& e = edges[G[x][i]];
    117           if(e.cap > e.flow) m = min(m, d[e.to]);
    118         }
    119         if(--num[d[x]] == 0) break;
    120         num[d[x] = m+1]++;
    121         cur[x] = 0;
    122         if(x != s) x = edges[p[x]].from;
    123       }
    124     }
    125     return flow;
    126   }
    127 };
    128 
    129 
    130 ISAP g;
    131 
    132 double get_dist(Point p1, Point p2) {
    133     return sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) );
    134 }
    135 
    136 int main() {
    137     int t;
    138     int n; double d;
    139    // freopen("a.txt","r",stdin);
    140     scanf("%d",&t);
    141     while(t--) {
    142         scanf("%d %lf",&n, &d);
    143         int sum = 0;
    144         for(int i = 0; i < n; i++) {
    145             scanf("%d %d %d %d",&point[i].x, &point[i].y, &point[i].ni, &point[i].mi);
    146             sum += point[i].ni;
    147         }
    148         //Dinic g;
    149         g.ClearAll(maxn);
    150         for(int i = 0; i < n; i++) {
    151             int left = i + 1; int right = n + left;
    152             g.AddEdge(0, left, point[i].ni);
    153             g.AddEdge(left, right, point[i].mi);
    154             g.AddEdge(right, left, point[i].mi);
    155             for(int j = i + 1; j < n; j++) {
    156                 if( i == j)
    157                     continue;
    158                 if(d - get_dist(point[i], point[j]) > 0.00001) {
    159                     g.AddEdge(right, j + 1, INF);
    160                     g.AddEdge(j + 1 + n, left, INF);
    161                 }
    162             }
    163         }
    164         //printf("*%d
    ",sum);
    165         int c = 0;
    166         for(int i = 0; i < n; i++) {
    167             int s = 0; int t = i + 1;
    168             g.init();
    169             if(g.MaxFlow(s, t, INF) == sum)
    170             printf(c++ ? " %d" : "%d",i);
    171             //printf("%d
    ",g.MaxFlow(s, t));
    172         }
    173         if(c == 0)
    174         printf("-1");
    175         puts("");
    176     }
    177     return 0;
    178 }
    View Code
  • 相关阅读:
    Gym102040 .Asia Dhaka Regional Contest(寒假自训第9场)
    Gym-101673 :East Central North America Regional Contest (ECNA 2017)(寒假自训第8场)
    Gym -102007 :Benelux Algorithm Programming Contest (BAPC 18) (寒假自训第5场)
    Gym .101879 USP Try-outs (寒假自训第七场)
    Gym.101908 Brazil Subregional Programming Contest(寒假自训第六场)
    Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)
    Gym .102021 .German Collegiate Programming Contest (GCPC 18) (寒假gym自训第三场)
    Gym.102059: 2018-2019 XIX Open Cup, Grand Prix of Korea(寒假gym自训第一场)
    【整理】简单的数学期望和概率DP
    猿助力下载地址
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/3748746.html
Copyright © 2011-2022 走看看