POJ 3498【最大流+拆点建图】

题意: 在X,Y坐标系中有N(N<=100)个冰块...有些冰块上有若干只企鹅..每只企鹅一次最多跳M距离..一个冰块在有Mi个企鹅离开..就会消失..问有哪些冰块可以作为集合点..就是所有企鹅都能成功到这个冰块上来.

这个题建图比较有意思。

把每块冰分成两个点i和i+n. i表示进入i冰块的点(可以有无数企鹅过来,所以从别的冰到i有边,容量为INF) i+n表示从i冰块出去的点(最多只能有Mi企鹅从这跳出去,所以从i到i+n有边,且容量为Mi)
从源点S到i有边(S, i, i点初始企鹅数).
从i到i+n有边(i, i+n, Mi). 表示第i块冰最多只有Mi个企鹅能跳走.
因为i+n表示的是第i个跳走的点,所以如果冰块i和j之间的距离<=企鹅能跳跃的距离M,有边(i+n, j, INF)
假设我们当前枚举第x块冰块作为集合点,那么(x分成x和x+n两个点)x点就是汇点(不是x+n点哦),我们只要计算到x点的流量是否==企鹅总数即可.

#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#define maxn 1000
#define INF 0x3f3f3f3f

using namespace std;
struct e {
    int from, to, w, next;
}edge[1000000];

struct p {
    int x, y;
}pos[10000];
int ss, tt;
int n;
double d;
int cur[maxn];
int cont;
int head[maxn];
int map[maxn][maxn];
int dis[maxn][maxn];
int divv[maxn];
int x[maxn], y[maxn], num[maxn], m[maxn];

bool check(p a, p b) {
    double dis = sqrt(pow(fabs(a.x - b.x), 2) + pow(fabs(a.y - b.y), 2));
    if (dis <= d)
        return true;
    else
        return false;

}

void add(int u, int v, int w) {
    edge[cont].from = u;
    edge[cont].to = v;
    edge[cont].w = w;
    edge[cont].next = head[u];
    head[u] = cont++;
}

void makediv() {
    memset(divv, 0, sizeof(divv));
    divv[ss] = 1;
    queue<int> Q;
    Q.push(ss);
    while (!Q.empty()) {
        int u = Q.front();
        Q.pop();
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int w = edge[i].w;
            int v = edge[i].to;
            if (divv[v] == 0 && w) {
                divv[v] = divv[u] + 1;
                Q.push(v);
            }
        }

    }

}

int DFS(int u, int maxflow, int tt) {
    if (u == tt)
        return maxflow;
    int ret = 0;
    for (int &i = cur[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        int w = edge[i].w;
        if (divv[v] == divv[u] + 1 && w) {
            int f = DFS(v, min(maxflow - ret, w), tt);
            edge[i].w -= f;
            edge[i ^ 1].w += f;
            ret += f;
            if (ret == maxflow)
                return ret;

        }
    }
    return ret;
}

int Dinic() {
    int ans = 0;
    while (1) {
        makediv();
        if (divv[tt] == 0)
            break;
        memcpy(cur, head, sizeof(head));
        ans += DFS(ss, INF, tt);
    }
    return ans;
}

void Build() {
    for (int i = 1; i <= n; i++) {
        add(ss, i, num[i]);
        add(i, ss, 0);
        add(i, i + n, m[i]);
        add(i + n, i, 0);
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i == j)
                continue;
            if (check(pos[i], pos[j])) {
                add(i + n, j, INF);
                add(j, i + n, 0);
            }
        }
    }
}

int main(void) {
    int t;
    int p_n;
    scanf("%d", &t);
    while (t--) {
        bool flag = false;
        ss = 0;
        p_n = 0;
        scanf("%d%lf", &n, &d);
        memset(head, -1, sizeof(head));
        for (int i = 1; i <= n; i++) {
            scanf("%d%d%d%d", &x[i], &y[i], &num[i], &m[i]);
            if (num)
                p_n += num[i];
            pos[i].x = x[i];
            pos[i].y = y[i];
        }

        vector<int> V;
        for (int i = 1; i <= n; i++) {
            tt = i;
            cont = 0;
            memset(head, -1, sizeof(head));
            Build();
            if (Dinic() == p_n) {
                flag = true;
                V.push_back(i - 1);
            }
        }
        if (!flag)
            printf("-1\n");
        else {
            for (int i = 0; i < (int)V.size(); i++)
                if (i != V.size() - 1)
                    printf("%d ", V[i]);
                else
                    printf("%d\n", V[i]);
        }

    }

    return 0;
}

原文地址:https://www.cnblogs.com/tennant/p/8975474.html

时间: 2024-12-21 02:55:13

POJ 3498【最大流+拆点建图】的相关文章

POJ 3422 HDU 2686,3376 费用流拆点建图

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3376 http://acm.hdu.edu.cn/showproblem.php?pid=2686 http://poj.org/problem?id=3422 POJ 3422为从矩阵左上角走到右下角,最多走k次,每个格子里的数字只能算一次,后面可以重复经过,求经过的各个数字的和的最大值. 拆点,入点向出点连流量为1,费用为当前格子负值的边,向下方,右方连边,流量为k,费用为0,起点连流量为1,

POJ 3281 Dining (网络流最大流 拆点建图 Edmonds-Karp算法)

Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10159   Accepted: 4676 Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulo

POJ 2312Battle City(BFS-priority_queue 或者是建图spfa)

1 /* 2 bfs搜索!要注意的是点与点的权值是不一样的哦! 3 空地到空地的步数是1, 空地到墙的步数是2(轰一炮+移过去) 4 所以用到优先队列进行对当前节点步数的更新! 5 */ 6 #include<iostream> 7 #include<queue> 8 #include<cstring> 9 #include<algorithm> 10 #include<cstdio> 11 using namespace std; 12 13

HDU2732Leapin&amp;#39; Lizards(最大流SAP,建图---折点法)

Leapin' Lizards Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1531    Accepted Submission(s): 623 Problem Description Your platoon of wandering lizards has entered a strange room in the labyr

HDU2732Leapin&#39; Lizards(最大流SAP,建图---折点法)

Leapin' Lizards Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1531    Accepted Submission(s): 623 Problem Description Your platoon of wandering lizards has entered a strange room in the labyr

Antenna Placement POJ - 3020 二分图匹配 匈牙利 拆点建图 最小路径覆盖

题意:图没什么用  给出一个地图 地图上有 点 一次可以覆盖2个连续 的点( 左右 或者 上下表示连续)问最少几条边可以使得每个点都被覆盖 最小路径覆盖       最小路径覆盖=|G|-最大匹配数                   证明:https://blog.csdn.net/qq_34564984/article/details/52778763 证明总的来说就是尽可能多得连边 边越多 可以打包一起处理得点就越多(这里题中打包指连续得两个点只需要一条线段就能覆盖) 拆点思想   :匈牙

HDU 3572 【最大流 &amp;&amp; 时间区间建图】

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5398    Accepted Submission(s): 1742 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

POJ 2195 一人一房 最小费用流 建图 水题

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 21010   Accepted: 10614 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertica

POJ 2226 最小点覆盖(经典建图)

Muddy Fields Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8881   Accepted: 3300 Description Rain has pummeled the cows' field, a rectangular grid of R rows and C columns (1 <= R <= 50, 1 <= C <= 50). While good for the grass, t