Ligthoj 1154--Penguins【最大流 && 拆点】
来源:互联网 发布:淘宝几点开店 编辑:程序博客网 时间:2024/06/05 22:55
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;}
- Ligthoj 1154--Penguins【最大流 && 拆点】
- Ligthoj 1155--Power Transmission【最大流 && 拆点】
- LightOJ 1154 - Penguins 最大流
- La (NWERC2007 Problem B )- March of the Penguins(最大流 拆点)
- POJ 3498 - March of the Penguins 拆点构图最大流
- poj 3498 March of the Penguins 点流量有限制的最大流
- (beginer) 网络流(拆点)UVA 12125 - March of the Penguins
- uva 12125 - March of the Penguins(最大流)
- POJ 3498 March of the Penguins(枚举+最大流)
- UVA 12125 - March of the Penguins(最大流)
- uva 12125 March of the Penguins (最大流)
- UVALive - 3972 March of the Penguins(最大流+枚举)
- POJ 3498 March of the Penguins(枚举+最大流)
- POJ 3498 March of the Penguins(枚举+最大流)
- Uva 12125 March of the Penguins(最大流)
- lightoj 1154 - Penguins 【拆点建图后枚举汇点 满流判可行解】
- POJ 3498 && HDU 2334 March of the Penguins(最大流-Dinic)
- POJ 3498 —— March of the Penguins (枚举+最大流)
- Linux命令-tar
- Annotation 和Spring Annotation 知识整理
- 1037. 在霍格沃茨找零钱(20)
- 两个子对话框传递参数
- Integer.valueOf(String) 方法之惑
- Ligthoj 1154--Penguins【最大流 && 拆点】
- android屏幕适配官方总结
- Unity3D项目优化:从Draw Calls到GC
- 1038. 统计同成绩学生(20)
- Codeforces Round #327 (Div. 2)D. Chip 'n Dale Rescue Rangers
- pdf转成html的转换方法是什么
- 在arcgis常见的叠加分析情况汇总 (转)
- (小知识点)activity全透明,mark
- Android L+ Theme 与 Toolbar 实例