LightOJ 1154 - Penguins 最大流
来源:互联网 发布:js获取option选中的值 编辑:程序博客网 时间:2024/06/05 23:08
题目:http://www.lightoj.com/volume_showproblem.php?problem=1154
题意:有n块浮冰,上面有一定数量的企鹅,企鹅每次跳跃时,会产生冲击力损坏起跳的浮冰,不损坏落下的浮冰,现在告诉你每块浮冰还能承受几次跳跃,问哪些浮冰能够让所有的企鹅聚齐。输入格式:首先一个t,代表测试数据组数,然后n d,代表浮冰块数和企鹅跳跃的最大距离,然后n行,每行 x y a b,分别代表浮冰坐标、浮冰上企鹅数、能承受冲击次数。
思路:首先预处理浮冰间的距离,因为要找到所有的满足条件的浮冰,那么我们枚举每个浮冰为汇点,从0向每个浮冰连边,容量为浮冰上企鹅数,对于每个浮冰,拆点连边,容量为能承受冲击的次数,限制经过的企鹅数。然后浮冰之间距离小于等于给定距离的连边,此时最大流的意义就是有几个企鹅能够到达汇点,如果等于企鹅总数,那就是满足条件的。还有浮冰编号是从0开始的
总结:拆点连边时一定要小心,不要连错,容量不要搞错!!!
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>using namespace std;const int N = 210;const int INF = 0x3f3f3f3f;struct edge{ int to, cap, next;}g[N*N*2];int head[N], iter[N], level[N];int n, cnt, _case = 0;void add_edge(int v, int u, int cap){ g[cnt].to = u, g[cnt].cap = cap, g[cnt].next = head[v], head[v] = cnt++; g[cnt].to = v, g[cnt].cap = 0, g[cnt].next = head[u], head[u] = cnt++;}bool bfs(int s, int t){ memset(level, -1, sizeof level); level[s] = 0; queue<int> que; que.push(s); while(! que.empty()) { int v = que.front(); que.pop(); for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(g[i].cap > 0 && level[u] < 0) { level[u] = level[v] + 1; que.push(u); } } } return level[t] == -1;}int dfs(int v, int t, int f){ if(v == t) return f; for(int &i = iter[v]; i != -1; i = g[i].next) { int u = g[i].to; if(g[i].cap > 0 && level[v] < level[u]) { int d = dfs(u, t, min(g[i].cap, f)); if(d > 0) { g[i].cap -= d, g[i^1].cap += d; return d; } } } return 0;}int dinic(int s, int t){ int flow = 0, f; while(true) { if(bfs(s, t)) return flow; memcpy(iter, head, sizeof head); while(f = dfs(s, t, INF),f > 0) flow += f; }}int main(){ int t; int x[N], y[N], num[N], cut[N]; double len, dis[N][N]; scanf("%d", &t); while(t--) { scanf("%d%lf", &n, &len); int sum = 0; for(int i = 1; i <= n; i++) { scanf("%d%d%d%d", x + i, y + i, num + i, cut + i); sum += num[i]; } for(int i = 1; i <= n; i++) //预处理浮冰间的距离 for(int j = i + 1; j <= n; j++) dis[i][j] = dis[j][i] = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])); bool flag = false; printf("Case %d: ", ++_case); for(int i = 1; i <= n; i++) //枚举所有浮冰为汇点 { cnt = 0; memset(head, -1, sizeof head); for(int j = 1; j <= n; j++) add_edge(0, j, num[j]); for(int j = 1; j <= n; j++) //拆点 add_edge(j, n + j, cut[j]); for(int j = 1; j <= n; j++) for(int k = j + 1; k <= n; k++) if(dis[j][k] <= len) { add_edge(j + n, k, cut[j]); //从j到k,因为拆点的限制,最多能通过cut[j]的流量,设为INF也可以,不容易搞错 add_edge(k + n, j, cut[k]); //从k到j,最多通过cut[k]的流量 } if(dinic(0, i) == sum) { if(flag) printf(" %d", i - 1); else printf("%d", i - 1), flag = true; } } if(! flag) printf("-1"); printf("\n"); } return 0;}
0 0
- LightOJ 1154 - Penguins 最大流
- Ligthoj 1154--Penguins【最大流 && 拆点】
- lightoj 1154 - 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(最大流)
- La (NWERC2007 Problem B )- March of the Penguins(最大流 拆点)
- POJ 3498 - March of the Penguins 拆点构图最大流
- poj 3498 March of the Penguins 点流量有限制的最大流
- POJ 3498 && HDU 2334 March of the Penguins(最大流-Dinic)
- POJ 3498 —— March of the Penguins (枚举+最大流)
- 【最大流】LightOJ-1153 Internet Bandwidth
- LightOJ 1153 - Internet Bandwidth【最大流】
- 第十四周项目59-排序函数模板
- 1014. 福尔摩斯的约会 (20)
- 最新学习框架和语言
- 数据结构复习——线性表(二)链表
- Quartz.NET c# 教程 - 课程五:SimpleTrigger
- LightOJ 1154 - Penguins 最大流
- http://www.shangxueba.com/jingyan/1866247.html
- 《疯狂Java讲义》——解释型语言和编译型语言
- 数据结构复习——线性表(三)栈
- 23种设计模式01--简单工厂
- sel类型(以后完善)
- Android学习(56) -- 断点续传多线程下载(Android)
- 数据结构复习——线性表(四)队列
- 总结一下新建Android项目前的准备工作