Ligthoj 1154--Penguins【最大流 && 拆点】

来源:互联网 发布:淘宝几点开店 编辑:程序博客网 时间:2024/06/05 22:55


1154 - Penguins
PDF (English)StatisticsForum
Time Limit: 4 second(s)Memory Limit: 32 MB

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.

A sample layout of ice floes with 3 penguins on them

Input

Input starts with an integer T (≤ 25), denoting the number of test cases.

Each case starts with the integer N (1 ≤ N ≤ 100) and a floating-point number D (0 ≤ D ≤ 105), denoting the number of ice pieces and the maximum distance a penguin can jump. After that there will be 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 (-10000 ≤ xi, yi ≤ 10000, 0 ≤ ni ≤ 10, 1 ≤ mi ≤ 200).

Output

For each case of input, print the case number and a space-separated list of 0-based indices of the pieces on which all penguins can meet. If no such piece exists, output -1.

Sample Input

Output for 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

Case 1: 1 2 4

Case 2: -1



题意:有n块大浮冰,现在已经给出每个浮冰的位置坐标、上面企鹅的数目以及可以承受的限度。现在你已经知道企鹅能够跳跃的最大距离,
问你所有企鹅能不能在某一块浮冰上相聚,若可以则输出所有可能相聚的浮冰编号(从0开始),反之输出-1。


解析:设置一个超级源点outset,超级汇点inset。把每个浮冰 i 看成一个点,把每个浮冰拆成两个点,左点: i ,右点:i + n。

具体见图如下:

(1)源点向每个点的左点建边,容量为每个点上的企鹅数目,

(2)除源点汇点外,每个点的左点向右点建边, 容量为每个点可以承受的最大限度

(3)根据企鹅能够跳跃的最大距离,两个相互可达的点之间建边,如点i, j: i + n --> j 和j + n --> i 。为什么这样,大家画个图就明白了

(4)枚举所有点 ,每个点的左点向汇点建图,然后跑一遍最大流,如果满流的话符合条件,输出点的编号。

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <math.h>#define maxn 1010#define maxm 1100000#define INF 0x3f3f3f3fusing namespace std;int n;double maxdis;int outset, inset;struct node {    int u, v, cap, flow, next;};node edge[maxm];int head[maxn], cnt, cur[maxn];int vis[maxn], dist[maxn];void init(){    cnt = 0;    memset(head, -1, sizeof(head));}void add(int u, int v, int w){    edge[cnt] = {u, v, w, 0, head[u]};    head[u] = cnt++;    edge[cnt] = {v, u, 0, 0, head[v]};    head[v] = cnt++;}double x[maxn], y[maxn];int maxnum[maxn], num[maxn];int Sumflow;double dis(double x1, double y1, double x2, double y2){    return sqrt((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2));}void Input(){    Sumflow = 0;    scanf("%d%lf", &n, &maxdis);    for(int i = 1; i <= n; ++i)        scanf("%lf%lf%d%d", &x[i], &y[i], &num[i], &maxnum[i]), Sumflow += num[i];}void getmap(){    init();    for(int i = 1; i <= n; ++i){        add(outset, i, num[i]);        add(i, i + n, maxnum[i]);        for(int j = i + 1; j <= n; ++j){                if(dis(x[i], y[i], x[j], y[j]) <= maxdis)                    add(j + n, i, INF), add(i + n, j, INF);        }    }}bool BFS(int st ,int ed){    queue<int>q;    memset(vis, 0 ,sizeof(vis));    memset(dist, -1, sizeof(dist));    vis[st] = 1;    dist[st] = 0;    q.push(st);    while(!q.empty()){        int u = q.front();        q.pop();        for(int i = head[u]; i != -1; i = edge[i].next){            node E = edge[i];            if(!vis[E.v] && E.cap > E.flow){                vis[E.v] = 1;                dist[E.v] = dist[u] + 1;                if(E.v == ed)                    return true;                q.push(E.v);            }        }    }    return false;}int DFS(int x, int ed, int a){    if(x == ed || a == 0)        return a;    int flow = 0, f;    for(int &i = cur[x]; i != -1; i = edge[i].next){        node &E = edge[i];        if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow))) > 0){            E.flow += f;            edge[i ^ 1].flow -= f;            a -= f;            flow += f;            if(a == 0)                break;        }    }    return flow;}int maxflow(int st, int ed){    int flowsum = 0;    while(BFS(st,ed)){        memcpy(cur, head, sizeof(head));        flowsum += DFS(st, ed, INF);    }    return flowsum;}int kcase = 1;void solve(){    outset = 0;    inset = 2 * n + 1;    printf("Case %d: ", kcase++);    int di = 0;    for(int i = 1; i <= n; ++i){        getmap();        add(i, inset, INF);        if(maxflow(outset, inset) == Sumflow){            if(di)                printf(" ");            printf("%d", i - 1);            di++;        }    }    if(di == 0)        printf("-1");    printf("\n");}int main (){    int T;    scanf("%d", &T);    while(T--){        Input();        solve();    }    return 0;}


1 0
原创粉丝点击