首页 > 代码库 > POJ 3498March of the Penguins

POJ 3498March of the Penguins

题目:题目链接

March of the Penguins
Time Limit: 8000MS Memory Limit: 65536K
Total Submissions: 4317 Accepted: 1957

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.

技术分享

A sample layout of ice floes with 3 penguins on them.

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 ≤ 100 000), denoting the number of ice pieces and the maximum distance a penguin can jump.

  • N lines, each line containing xiyini 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 ≤ xiyi ≤ 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

Northwestern Europe 2007

题意:

        有一群企鹅分布在一些浮冰(容量无限大)上。问你这些企鹅能不能到同一块浮冰上,如果能,输出能够。

        题目有如下限制:

        n块浮冰,给出每块浮冰的位置,每块浮冰上有一定数额的企鹅,且两块浮冰能通过的条件是他们的距离不大于d。

        并且每块浮冰能接受离开该浮冰的企鹅数有限制。


题解:

        这是一道最大流的题目。

        题目的限制条件在于离开浮冰企鹅数有限制,我们可以理解为把该浮冰作为中转的企鹅数限制。由于浮冰是一个点,所以我们进行拆点,把限制条件放在了边上(i,i+n)。

        然后我们进行枚举终点,来判断是不是满流。

        建图的技巧在于我们设置一个超级源,与拆点之后的i连接,容量定为mi。至于终点的话,加入我们枚举的聚集在一起的浮冰为x,我们则设x为终点,并不是设x+n为终点。

        每枚举完一个点,注意要把图中的流清零。

代码:

Source Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL __int64
const int  MOD = 1e9 + 7;
const int N = 2e2 + 15;
const int INF = (1 << 30) - 1;
const int letter = 130;
using namespace std;
int n;
double d1;
LL x[N], y[N], n1[N], m[N];
struct node
{
    int from, to, cap, flow;
};
vector<node>edges;
vector<int>G[N];
int d[N], cur[N];
int s, t;
void init()
{
    edges.clear();
    for(int i = 0; i < N; i++) G[i].clear();
}
void addedge(int from, int to, int cap)
{
    edges.push_back((node)
    {
        from, to, cap, 0
    });
    edges.push_back((node)
    {
        to, from, 0, 0
    });
    int vs = edges.size();
    G[from].push_back(vs - 2);
    G[to].push_back(vs - 1);
}
bool bfs(int s, int t)
{
    memset(d, -1, sizeof(d));
    queue<int>q;
    while(!q.empty()) q.pop();
    q.push(s);
    d[s] = 0;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        for(int i = 0; i < G[x].size(); i++)
        {
            node &e = edges[G[x][i]];
            if(d[e.to] < 0 && e.cap > e.flow)
            {
                d[e.to] = d[x] + 1;
                if(e.to == t) return true;
                q.push(e.to);
            }
        }
    }
    return false;
}
int dfs(int x, int a)
{
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int &i = cur[x]; i < G[x].size(); i++)
    {
        node &e = edges[G[x][i]];
        if(d[x] + 1 == d[e.to] && ( f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
        {
            flow += f;
            a -= f;
            edges[G[x][i]].flow += f;
            edges[G[x][i] ^ 1].flow -= f;
            if(a == 0) break;
        }
    }
    return flow;
}
int maxflow(int s, int t)
{
    int flow = 0;
    while(bfs(s, t))
    {
        memset(cur, 0, sizeof(cur));
        flow += dfs(s, INF);
    }
    return flow;
}
bool ok(int x1, int y1, int x2, int y2, double d)
{
    if(sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) <= d) return true;
    return false;
}
int main()
{
    int tc;
    scanf("%d", &tc);
    while(tc--)
    {
        scanf("%d%lf", &n, &d1);
        s = 0;
        init();
        LL sum = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%I64d%I64d%I64d%I64d", x + i, y + i, n1 + i, m + i);
            sum += n1[i];
        }
        ///jiantu
        for(int i = 1; i <= n; i++)
            addedge(i, i + n, m[i]); ///chai
        for(int i = 1; i <= n; i++)
            addedge(s, i, n1[i]);
        for(int i = 1; i <= n; i++)
            for(int j = i + 1; j <= n; j++)
            {
                if(ok(x[i], y[i], x[j], y[j], d1)) ///nbn
                {
                    addedge(i + n, j, INF);
                    addedge(j + n, i, INF);
                }
            }
        ///meiju
        int flag = 0;///geshi
        for(int i = 1; i <= n; i++)
        {
            t = i;
            int ans = maxflow(s, t);
            if(ans == sum)
            {
                if(flag) printf(" %d", i - 1);
                else printf("%d", i - 1);
                flag = 1;
            }
            for(int i = 0; i < edges.size(); i++)
                edges[i].flow = 0;
        }
       if(flag) printf("\n");
       else puts("-1");
    }

    return 0;
}


POJ 3498March of the Penguins