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. 数据库函数(Left、Right)

    MySQL 字符串截取函数:left(), right(), substring(), substring_index().还有 mid(), substr().其中,mid(), substr()  ...

  2. Linux下安装 nginx

    安装依赖 yum install gcc yum install pcre-devel yum install zlib zlib-devel yum install openssl openssl- ...

  3. CentOS7.5二进制安装MySQL-5.6.40

    安装依赖 yum install -y gcc gcc-c++ automake autoconf yum -y install cmake bison-devel ncurses-devel lib ...

  4. shell基础知识---与监听服务器长连接端口状态

    从未写过脚本我的最近接了俩脚本的需求,就在这分享一下我的我学到基础知识主要就四部分内容 一.变量 变量的定义 string='字符串' string="字符串" num=808st ...

  5. Dubbo 安装ZooKeeper环境

    一.在Windows 安装ZooKeeper 1.下载ZooKeeper 2.解压,修改ZooKeeper配置文件 复制一份zoo_sample.cfg文件,改名位zoo.cfg,打开编辑,设置数据保 ...

  6. 前端优化:css雪碧图实践应用详解

    一 为什么需要使用雪碧图 二CSS雪碧图原理及应用 前端是接近用户体验的一个项目组成部分,合适的优化能够大大减少网页响应时间,合理的资源加载自然成为了工作中的要务,现在就结合实例讲解到底什么是css雪 ...

  7. Centos7 Redis3.0 集群搭建备忘

    (要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下) 127.0.0.1:7000 127.0.0. ...

  8. ElasticSearch5插件安装

    http://blog.csdn.net/napoay/article/details/53896348 #更新 sudo yum update -y sudo rpm -ivh http://dl. ...

  9. centos升级数据库

    Centos下升级MySQL数据库 备份数据 $ mysqldump -u xxx -h xxx -P 3306 -p --all-databases > databases.sql 查看版本 ...

  10. Java学习笔记二十七:Java中的抽象类

    Java中的抽象类 一:Java抽象类: 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就 ...