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


题意:

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

        题目有如下限制:

        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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值