Description

A group of Mtourists are walking along the Karlutka river. They want to cross the river, but they couldn't find a bridge. Fortunately, there are some piles of rubbish floating in the water, and the tourists have decided to try to cross the river by jumping from one pile to another. 
tourist can move up to D meters in any direction at one jump. One jump takes exactly one second. tourists know that the river is W meters wide, and they have estimated the coordinates of rubbish piles ( XiYi) and the capacity of each pile ( Ci, the maximum number of tourists that this pile can hold at the same time). Rubbish piles are not very large and can be represented as points. The river flows along the X axis. tourists start on the river bank at 0 by Y axis. The Ycoordinate of the opposite bank is W
tourists would like to know if they can get to the opposite bank of the river, and how long it will take.

Input

First line of input consists of four integers: number of rubbish piles N (0 ≤ N ≤ 50), number of touristM (0 < M ≤ 50), maximum length of tourist's jump D (0 ≤ D ≤ 1000), and width of the river W (0 < W ≤ 1000) Following N lines describe the rubbish piles, each line consists of three integers: (0 < Xi < 1000, 0 < YiW, 0 ≤ Ci ≤ 1000) — pile coordinates and capacity.

Output

Output a single number indicating the minimal time (in seconds) in which all tourists will be able to cross the river, or the line " IMPOSSIBLE" if it is impossible to cross the river.
 

题目大意:M 个人要过河,,河宽为 W。河上有N个垃圾,给出垃圾的坐标以及垃圾能同时容纳的人数,现在这 M 个人一下能跳距离D,问最少需要多少时间才可以使所有人到达对岸。跳一步一秒。 (开始人都在 X 轴上.对岸可以看为 Y =W 的一条直线)

思路:二分答案,判定性的最大流。最少用时间1到达对岸,最后用时间N+M到达对岸(假设要经过全部垃圾并且全部垃圾都只能站一个人)。假设现在二分的答案为mid,那么对于每个垃圾分成mid-1份,每份代表一个时间,再每个时间分成两份P、P'。如果从X轴能走到某点P,那么对所有时间,S连一条边到P。如果从某点P能走到对岸,那么对所有时间,P'连一条边到T。然后对所有时间每个点P连一条边到P',容量为该点能同时站多少人。最后所有距离在D以内的,对每个时间t,连边(P,t)→(Q,t+1),(Q,t)→(P,t+1)。最大流即为用mid的时间能过去多少人。二分答案即可。这种做法正确是因为:每个点的时间t只能走到t+1的时间,而在每个时间里通过某一点的流量不大于该点的容量,在任何时刻都能从S出发和到达T。

另外

SAP(62MS):

 #include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std; const int MAXN = * * ;
const int MAXE = MAXN * ;
const int INF = 0x7fff7fff; struct SAP {
int vis[MAXN], head[MAXN];
int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
int to[MAXE], flow[MAXE], next[MAXE];
int ecnt, st, ed; void init(int ss, int tt) {
memset(head, , sizeof(head));
ecnt = ;
st = ss; ed = tt;
} void addEdge(int u,int v,int f) {
to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} int Max_flow() {
int ans = , minFlow = INF, n = ed, u;
for (int i = ; i <= n; ++i){
cur[i] = head[i];
gap[i] = dis[i] = ;
}
u = pre[st] = st;
gap[] = n;
while (dis[st] < n){
bool flag = false;
for (int &p = cur[u]; p; p = next[p]){
int v = to[p];
if (flow[p] > && dis[u] == dis[v] + ){
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed){
ans += minFlow;
while (u != st){
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if (flag) continue;
int minDis = n-;
for (int p = head[u]; p; p = next[p]){
int v = to[p];
if (flow[p] && dis[v] < minDis){
minDis = dis[v];
cur[u] = p;
}
}
if (--gap[dis[u]] == ) break;
gap[dis[u] = minDis+]++;
u = pre[u];
}
return ans;
}
} G; const int MAX = ; struct Point {
int x, y, c;
}; int dis2(const Point &a, const Point &b) {
int xx = a.x - b.x, yy = a.y - b.y;
return xx * xx + yy * yy;
} int n, m, d, w;
Point rub[MAX]; #define FOR(i, s, t) for(int i = s; i <= t; ++i)
#define get_num(i, t) ((i - 1) * 2 * (mid - 1) + 2 * (t - 1) + 1) void solve() {
int left = , right = n + m + ;
while(left < right) {
int mid = (left + right) >> ;
int ss = n * (mid - ) * + , st = ss + , tt = ss + ;
G.init(st, tt);
G.addEdge(st, ss, m);
FOR(i, , n) {
if(rub[i].y <= d) {
FOR(t, , mid - ) G.addEdge(ss, get_num(i, t), INF);
}
if(rub[i].y + d >= w) {
FOR(t, , mid - ) G.addEdge(get_num(i, t) + , tt, INF);
}
}
FOR(i, , n) FOR(t, , mid - ) {
int num = get_num(i, t);
G.addEdge(num, num + , rub[i].c);
if(t < mid - ) G.addEdge(num + , num + , INF);
}
FOR(i, , n) FOR(j, , n) {
if(i == j || dis2(rub[i], rub[j]) > d * d) continue;
FOR(t, , mid - ) G.addEdge(get_num(i, t) + , get_num(j, t + ), INF);
}
int ans = G.Max_flow();
if(ans < m) left = mid + ;
else right = mid;
//printf("%d %d\n", mid, ans); system("pause");
}
if(right == n + m + ) puts("IMPOSSIBLE");
else printf("%d\n", right);
} int main() {
scanf("%d%d%d%d", &n, &m, &d, &w);
FOR(i, , n) scanf("%d%d%d", &rub[i].x, &rub[i].y, &rub[i].c);
FOR(i, , n) if(rub[i].c > m) rub[i].c = m;
if(w <= d) printf("1\n");
else solve();
}

DINIC(15MS):

 #include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std; const int MAXN = * * ;
const int MAXE = MAXN * ;
const int INF = 0x7fff7fff; struct Dinic {
int n, m, st, ed, ecnt;
int vis[MAXN], head[MAXN];
int cur[MAXN], d[MAXN];
int to[MAXE], next[MAXE], flow[MAXE]; void init(){
memset(head,,sizeof(head));
ecnt = ;
} void addEdge(int u,int v,int f) {
to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} bool bfs() {
memset(vis, , sizeof(vis));
queue<int> que; que.push(st);
d[st] = ; vis[st] = true;
while(!que.empty()){
int u = que.front(); que.pop();
for(int p = head[u]; p; p = next[p]){
int v = to[p];
if (!vis[v] && flow[p] > ){
vis[v] = ;
d[v] = d[u] + ;
que.push(v);
if(v == ed) return true;
}
}
}
return vis[ed];
} int dfs(int u, int a) {
if(u == ed || a == ) return a;
int outflow = , f;
for(int &p = cur[u]; p; p = next[p]){
int v = to[p];
if(d[u] + == d[v] && (f = dfs(v, min(a, flow[p]))) > ){
flow[p] -= f;
flow[p ^ ] += f;
outflow += f;
a -= f;
if(a == ) break;
}
}
return outflow;
} int Maxflow(int ss, int tt, int nn) {
st = ss; ed = tt;
int ans = ;
while(bfs()){
for(int i = ; i <= ed; ++i) cur[i] = head[i];
ans += dfs(st, INF);
}
return ans;
}
} G; const int MAX = ; struct Point {
int x, y, c;
}; int dis2(const Point &a, const Point &b) {
int xx = a.x - b.x, yy = a.y - b.y;
return xx * xx + yy * yy;
} int n, m, d, w;
Point rub[MAX]; #define FOR(i, s, t) for(int i = s; i <= t; ++i)
#define get_num(i, t) ((i - 1) * 2 * (mid - 1) + 2 * (t - 1) + 1) void solve() {
int left = , right = n + m + ;
while(left < right) {
int mid = (left + right) >> ;
int ss = n * (mid - ) * + , st = ss + , tt = ss + ;
G.init();
G.addEdge(st, ss, m);
FOR(i, , n) {
if(rub[i].y <= d) {
FOR(t, , mid - ) G.addEdge(ss, get_num(i, t), INF);
}
if(rub[i].y + d >= w) {
FOR(t, , mid - ) G.addEdge(get_num(i, t) + , tt, INF);
}
}
FOR(i, , n) FOR(t, , mid - ) {
int num = get_num(i, t);
G.addEdge(num, num + , rub[i].c);
if(t < mid - ) G.addEdge(num + , num + , INF);
}
FOR(i, , n) FOR(j, , n) {
if(i == j || dis2(rub[i], rub[j]) > d * d) continue;
FOR(t, , mid - ) G.addEdge(get_num(i, t) + , get_num(j, t + ), INF);
}
int ans = G.Maxflow(st, tt, tt);
if(ans < m) left = mid + ;
else right = mid;
//printf("%d %d\n", mid, ans); system("pause");
}
if(right == n + m + ) puts("IMPOSSIBLE");
else printf("%d\n", right);
} int main() {
scanf("%d%d%d%d", &n, &m, &d, &w);
FOR(i, , n) scanf("%d%d%d", &rub[i].x, &rub[i].y, &rub[i].c);
FOR(i, , n) if(rub[i].c > m) rub[i].c = m;
if(w <= d) printf("1\n");
else solve();
}

BFS+ISAP(15MS):

 #include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std; const int MAXN = * * ;
const int MAXE = MAXN * ;
const int INF = 0x7fff7fff; struct SAP {
int head[MAXN];
int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
int to[MAXE], flow[MAXE], next[MAXE];
int ecnt, st, ed, n; void init(int ss, int tt, int nn) {
memset(head, , sizeof(head));
ecnt = ;
st = ss; ed = tt; n = nn;
} void addEdge(int u,int v,int f) {
to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} void bfs() {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
++gap[dis[u]];
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if (dis[v] > n && flow[p ^ ] > ) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int Max_flow() {
int ans = , minFlow = INF, u;
for (int i = ; i <= n; ++i){
cur[i] = head[i];
gap[i] = dis[i] = ;
}
u = pre[st] = st;
//gap[0] = n;
bfs();
while (dis[st] < n){
bool flag = false;
for (int &p = cur[u]; p; p = next[p]){
int v = to[p];
if (flow[p] > && dis[u] == dis[v] + ){
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed){
ans += minFlow;
while (u != st){
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if (flag) continue;
int minDis = n-;
for (int p = head[u]; p; p = next[p]){
int v = to[p];
if (flow[p] && dis[v] < minDis){
minDis = dis[v];
cur[u] = p;
}
}
if (--gap[dis[u]] == ) break;
gap[dis[u] = minDis+]++;
u = pre[u];
}
return ans;
}
} G; const int MAX = ; struct Point {
int x, y, c;
}; int dis2(const Point &a, const Point &b) {
int xx = a.x - b.x, yy = a.y - b.y;
return xx * xx + yy * yy;
} int n, m, d, w;
Point rub[MAX]; #define FOR(i, s, t) for(int i = s; i <= t; ++i)
#define get_num(i, t) ((i - 1) * 2 * (mid - 1) + 2 * (t - 1) + 1) void solve() {
int left = , right = n + m + ;
while(left < right) {
int mid = (left + right) >> ;
int ss = n * (mid - ) * + , st = ss + , tt = ss + ;
G.init(st, tt, tt);
G.addEdge(st, ss, m);
FOR(i, , n) {
if(rub[i].y <= d) {
FOR(t, , mid - ) G.addEdge(ss, get_num(i, t), INF);
}
if(rub[i].y + d >= w) {
FOR(t, , mid - ) G.addEdge(get_num(i, t) + , tt, INF);
}
}
FOR(i, , n) FOR(t, , mid - ) {
int num = get_num(i, t);
G.addEdge(num, num + , rub[i].c);
if(t < mid - ) G.addEdge(num + , num + , INF);
}
FOR(i, , n) FOR(j, , n) {
if(i == j || dis2(rub[i], rub[j]) > d * d) continue;
FOR(t, , mid - ) G.addEdge(get_num(i, t) + , get_num(j, t + ), INF);
}
int ans = G.Max_flow();
if(ans < m) left = mid + ;
else right = mid;
//printf("%d %d\n", mid, ans); system("pause");
}
if(right == n + m + ) puts("IMPOSSIBLE");
else printf("%d\n", right);
} int main() {
scanf("%d%d%d%d", &n, &m, &d, &w);
FOR(i, , n) scanf("%d%d%d", &rub[i].x, &rub[i].y, &rub[i].c);
FOR(i, , n) if(rub[i].c > m) rub[i].c = m;
if(w <= d) printf("1\n");
else solve();
}

SGU 438 The Glorious Karlutka River =)(最大流)的更多相关文章

  1. SGU 438 The Glorious Karlutka River =) ★(动态+分层网络流)

    [题意]有一条东西向流淌的河,宽为W,河中有N块石头,每块石头的坐标(Xi, Yi)和最大承受人数Ci已知.现在有M个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳D米,每跳一次耗时1秒 ...

  2. SGU 0438 The Glorious Karlutka River =) 动态流

    题目大意:有一条东西向流淌的河,宽为W,河中有N块石头,每块石头的坐标(Xi, Yi)和最大承受人数Ci已知.现在有M个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳D米,每跳一次耗时1 ...

  3. SGU438 The Glorious Karlutka River =)(最大流)

    题目大概说有m个人要过一条宽W的河,人最远跳远距离是d,河上有n个垃圾堆,每个垃圾堆都有坐标和同一时间能容纳的人数,问所有人最少要跳几次才能跳到对岸. 又是一题根据时间拆点的最大流. 二分时间建容量网 ...

  4. The Glorious Karlutka River =)

    sgu438:http://acm.sgu.ru/problem.php?contest=0&problem=438 题意:有一条东西向流淌的河,宽为 W,河中有 N 块石头,每块石头的坐标( ...

  5. SGU438 The Glorious Karlutka River =)

    传送门 sgu原来搬到cf了呀点了好几个链接才找到233 传说中的动态流(?) 反正很暴力就对了QwQ 有容量限制->拆点 对于每个点拆成入点和出点 时间限制->分层 对于每个时刻的每个石 ...

  6. SGU438_The Glorious Karlutka River =)

    好题,有一些人在河的一边,想通过河里的某些点跳到对岸去.每个点最多只能承受一定数量的人,每人跳跃一次需要消耗一个时间.求所有人都过河的最短时间. 看网上说是用了什么动态流的神奇东东.其实就是最大流吧, ...

  7. SGU 185 Two shortest 最短路+最大流

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21068 Yesterday Vasya and Petya qua ...

  8. sgu 176 上下界网络流最小可行流带输出方案

    算法步骤: 1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流. 2. 加上刚才没有加上的那条边p 3. 再 ...

  9. Soj题目分类

    -----------------------------最优化问题------------------------------------- ----------------------常规动态规划 ...

随机推荐

  1. 开发类似"音速启动"的原创工具简码"万能助手"的过程中对ztree.js与win标准控件treeview、HTMLayout树形框等优缺点的比较

    在开发类似"音速启动"的桌面快捷方式管理软件简码"万能助手"的早期规划中,曾经考虑过几种树形框方案: ztree.js.win标准控件treeview.HTML ...

  2. 使用JDK开发WebServrice案例

    使用JDK开发WebServrice案例: 一.开发WebService服务器端 第一步:创建Java工程 ,创建相应的包(服务端)使用JDK开发(1.6以上版本) 第二步:建一个接口WebServi ...

  3. 关于如何去Apple.cn下载Xcode以及模拟器包

    前言:对于一个懒惰的iOS开发,Xcode的更新我是迟迟没有去下载.有人或许会说:你并不是一个合格的iOS开发者! T3T 我承认自己缺少拓新精神,Apple的尿性是:坑死第一批体验者不偿命~表示本人 ...

  4. go语言学习(一):数组/切片

    学习区块链之后,发现还要学习加密,接触到的视频是:Go的crypto包,所以开始接触Go.因为和solidity有些相似,但是比solidity简单一些,就开始放松的心态去学习.每天翻着go菜鸟教程, ...

  5. react-router-dom实现全局路由登陆拦截

    相比与vue的路由集中式管理,能够很好的进行统一的路由操作,react的路由看起来更乱,想要进行像vue的全局路由管理不是那么得心应手.在我们的项目中,有很多页面是需要登陆权限验证的,最好的方式就是能 ...

  6. 「PHP」设计模式介绍

    引言   最近再看PHP设计模式相关的一些技术文章,网上有关PHP的设计模式范例很少,这里做一些总结仅供参考,不足之处望提出. 参考资料: <大话设计模式>程杰   什么是设计模式   设 ...

  7. 3D立方体

    效果图 主要用到的3D属性 1.保留子元素的3d属性:transform-style:preserve-3d; 2.2D变形属性: ①transform:translate()平移,分X轴,Y轴,Z轴 ...

  8. 【Hive六】Hive调优小结

    Hive调优 Hive调优 Fetch抓取 本地模式 表的优化 小表.大表Join 大表Join大表 MapJoin Group By Count(Distinct) 去重统计 行列过滤 动态分区调整 ...

  9. S3C2440上LCD驱动(FrameBuffer)实例开发讲解(一)

    一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二.背景知识 ...

  10. 常量的三种定义方式和static在c语言中的三种修饰

    c语言的常量在执行期间为固定值,在定义后无法被修改常量可以是任何的数据基本类型,可以为整形,浮点常量,字符和字符串常量1,使用const关键字2, 使用宏定义3,使用枚举常量 枚举: #include ...