uva 12125 March of the Penguins (最大流)

来源:互联网 发布:淘宝网木质沙发 编辑:程序博客网 时间:2024/09/21 08:19

uva 12125 March of the Penguins

题目大意:网格上有n(n<=100)片荷叶,初始时第i片荷叶上有ni只企鹅(0<=ni<=10)。由于承受能力有限,第i片荷叶最多只能承受mi(1<=mi<=200)只企鹅从上米娜跳走。一只企鹅最多能跳D(D<=105)单位距离。要求所有企鹅在同一片荷叶上集合。问哪些荷叶可以成为企鹅们集合的地点。

解题思路:企鹅为什么不游泳……。每片荷叶是有容量的,所以每片荷叶都要进行拆点,拆成两个点,容量为这片荷叶所能承受的最多跳跃次数。设置一个超级源点,连向所有的荷叶,容量为该荷叶上初始企鹅的数量。然后枚举每片荷叶作为起点,看最后流出的最大流会不会等于所有企鹅的数量,会的话,记录当前荷叶(注意:荷叶编号是从0开始的)。每次求最大流记得初始化边的流量。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <queue>using namespace std;const int PO = 105;const int N = 1000;const int M = 20000;const int INF = 0x3f3f3f3f;typedef long long ll;int n, rec[N], s, t, cnt, sum;double l;struct Node{    int x, y, a, b;}node[PO];struct Edge{    int from, to, cap, flow; };vector<Edge> edges;vector<int> G[M];void init() {    sum = 0;    cnt = 0;    for (int i = 0; i < M; i++) G[i].clear();    edges.clear();}void addEdge(int from, int to, int cap) {    edges.push_back((Edge){from, to, cap, 0});    edges.push_back((Edge){to, from, 0, 0});    int m = edges.size();    G[from].push_back(m - 2);    G[to].push_back(m - 1);} int vis[N], d[N];int BFS() {    memset(vis, 0, sizeof(vis));    queue<int> Q;    Q.push(s);    d[s] = 0;    vis[s] = 1;    while (!Q.empty()) {        int u = Q.front(); Q.pop();         for (int i = 0; i < G[u].size(); i++) {            Edge &e = edges[G[u][i]];               if (!vis[e.to] && e.cap > e.flow) {                vis[e.to] = 1;                  d[e.to] = d[u] + 1;                Q.push(e.to);            }        }    }    return vis[t];}int cur[N];int DFS(int u, int a) {    if (u == t || a == 0) return a;    int flow = 0, f;     for (int &i = cur[u]; i < G[u].size(); i++) {        Edge &e = edges[G[u][i]];        if (d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {            e.flow += f;                edges[G[u][i]^1].flow -= f;            flow += f;            a -= f;            if (a == 0) break;        }    }    return flow;}int dinic() { //dinic算法求最大流    int ans = 0;    while (BFS()) {        memset(cur, 0, sizeof(cur));            ans += DFS(s, INF);    }    return ans;} double getDis(int x, int y) {    double px = node[x].x, py = node[x].y;    double qx = node[y].x, qy = node[y].y;    return pow(px - qx, 2) + pow(py - qy, 2);}void input() {    s = 0;    scanf("%d %lf", &n, &l);    double a, b;    int c, d;    for (int i = 1; i <= n ;i++) {        scanf("%lf %lf %d %d",&a, &b, &c, &d);              sum += c;        node[i] = (Node){a, b, c, d};        addEdge(i, i + n, d);        addEdge(s, i, c);       }    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= n; j++) {            if (i == j) continue;            if (l * l - getDis(i, j) > 1e-9) {                addEdge(i + n, j, INF);            }           }       }}void ClearF() {    for (int i = 0; i < edges.size(); i++) {        edges[i].flow = 0;      }}void solve() {    for (int i = 1; i <= n; i++) {        ClearF();        t = i;        int temp = dinic();        if (temp == sum) {            rec[cnt++] = i;         }    }}int main() {    int T;    scanf("%d", &T);    while (T--) {        init();        input();        solve();        if (!cnt) printf("-1");        else {            printf("%d", rec[0] - 1);            for (int i = 1; i < cnt; i++) {                printf(" %d", rec[i] - 1);            }        }puts("");    }    return 0;}
0 0
原创粉丝点击