好题,有一些人在河的一边,想通过河里的某些点跳到对岸去。每个点最多只能承受一定数量的人,每人跳跃一次需要消耗一个时间。求所有人都过河的最短时间。

看网上说是用了什么动态流的神奇东东。其实就是最大流吧,不过是一个很有意思的模型。

每递增一个时间,所有的点增加一层,因为有的人可以站在上一个点不走动,最终每个点分别表示河中的某个点在某个特定的时刻。

同时为了保证人数在点的承受范围之内,拆点即可。

一直增加层数,直到最大流达到m为止即可。

召唤代码君:

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 55555
#define maxm 9999999
using namespace std; int to[maxm],next[maxm],c[maxm],first[maxn],edge;
int Q[maxm],bot,top,node;
int tag[maxn],d[maxn],TAG=;
int L[],R[];
bool can[maxn],iq[maxn];
int X[],Y[],C[],connect[][];
int n,m,D,W,s,t,ans; int addnode()
{
first[++node]=-;
return node;
} void addedge(int U,int V,int W)
{
edge++;
to[edge]=V,c[edge]=W,next[edge]=first[U],first[U]=edge;
edge++;
to[edge]=U,c[edge]=,next[edge]=first[V],first[V]=edge;
} bool _input()
{
bot=,top=;
scanf("%d%d%d%d",&n,&m,&D,&W);
for (int i=; i<=n; i++)
{
iq[i]=false;
scanf("%d%d%d",&X[i],&Y[i],&C[i]);
if (C[i]==)
{
i--,n--;
continue;
}
if (Y[i]<=D) Q[++top]=i,iq[i]=true;
}
memset(connect,false,sizeof connect);
for (int i=; i<=n; i++)
for (int j=; j<=n; j++)
if (i!=j && (X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j])<=D*D)
connect[i][j]=connect[j][i]=true;
while (bot<=top)
{
int cur=Q[bot++];
if (Y[cur]+D>=W) return true;
for (int i=; i<=n; i++)
if (connect[cur][i] && !iq[i]) Q[++top]=i,iq[i]=true;
}
if (D<W) return false;
else return true;
} void build_init_graph()
{
edge=-,node=;
s=addnode(),t=addnode();
for (int i=; i<=n; i++) L[i]=addnode(),R[i]=addnode();
for (int i=; i<=n; i++)
{
addedge(L[i],R[i],C[i]);
if (Y[i]<=D) addedge(s,L[i],C[i]);
if (Y[i]+D>=W) addedge(R[i],t,C[i]);
}
} bool bfs()
{
Q[bot=top=]=t,d[t]=,tag[t]=++TAG,can[t]=false;
while (bot<=top)
{
int cur=Q[bot++];
for (int i=first[cur]; i!=-; i=next[i])
if (c[i^]> && tag[to[i]]!=TAG)
{
tag[to[i]]=TAG,d[to[i]]=d[cur]+;
can[to[i]]=false,Q[++top]=to[i];
if (to[i]==s) return true;
}
}
return false;
} int dfs(int cur,int num)
{
if (cur==t) return num;
int tmp=num,k;
for (int i=first[cur]; i!=-; i=next[i])
if (c[i]> && d[to[i]]==d[cur]- && tag[to[i]]==TAG && !can[to[i]])
{
k=dfs(to[i],min(num,c[i]));
if (k) num-=k,c[i]-=k,c[i^]+=k;
if (num==) break;
}
if (num) can[cur]=true;
return tmp-num;
} int maxflow()
{
int tot=;
while (bfs()) tot+=dfs(s,maxm);
return tot;
} int main()
{
if (!_input()) { puts("IMPOSSIBLE"); return ; }
if (D>=W) { puts(""); return ; }
build_init_graph();
for (ans=; maxflow()<m; ans++)
{
for (int i=; i<=edge; i+=) if (c[i]>) c[i-]+=c[i],c[i]=;
for (int i=; i<=n; i++)
{
L[i]=addnode();
if (Y[i]<=D) addedge(s,L[i],C[i]);
for (int j=; j<=n; j++)
if (connect[i][j]) addedge(R[j],L[i],C[i]);
}
for (int i=; i<=n; i++)
{
R[i]=addnode();
addedge(L[i],R[i],C[i]);
if (Y[i]+D>=W) addedge(R[i],t,C[i]);
}
}
printf("%d\n",ans);
return ;
}

SGU438_The Glorious Karlutka River =)的更多相关文章

  1. SGU 438 The Glorious Karlutka River =)(最大流)

    Description A group of Mtourists are walking along the Karlutka river. They want to cross the river, ...

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

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

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

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

  4. The Glorious Karlutka River =)

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

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

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

  6. SGU438 The Glorious Karlutka River =)

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

  7. Soj题目分类

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

  8. Moon River

    读书笔记系列链接地址http://www.cnblogs.com/shoufengwei/p/5714661.html.        昨晚无意中听到了一首英文歌曲,虽不知其意,但是瞬间就被优美的旋律 ...

  9. poj[3093]Margaritas On River Walk

    Description One of the more popular activities in San Antonio is to enjoy margaritas in the park alo ...

随机推荐

  1. Python之面向对象的组合、多态、菱形问题、子类中重用父类的两种方式

    一.组合 ''' 1.什么是组合 组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象 2.为何用组合 组合也是用来解决类与类直接代码冗余问题的 3.如何用组合 ''' # 继承减少代 ...

  2. 使用VMWareWorkstation10搭建学习环境笔记

    第一节:介绍虚拟化技术 虚拟化技术1.在一台计算机运行多个操作系统2.教学环境 测试环境3.和硬件无关4.P to V   物理机->虚拟机(Physical to Virtual)    V ...

  3. Python练习——矩形、直角三角形、乘法表

    一.矩形 #******输入行和列,打印相应的矩形******# width = input("宽:") longth = input("长:") if (wi ...

  4. rest的Web服务端获取http请求头字段

    如上图所示 输出的i就是获取的头字段的值 (仅自己记录)

  5. Netty源码分析第3章(客户端接入流程)---->第5节: 监听读事件

    Netty源码分析第三章: 客户端接入流程 第五节: 监听读事件 我们回到AbstractUnsafe的register0()方法: private void register0(ChannelPro ...

  6. Flink BLOB架构

    Flink中支持的BLOB文件类型 jar包 被user classloader使用的jar包 高负荷RPC消息 1. RPC消息长度超出了akka.framesize的大小 2. 在HA摸式中,利用 ...

  7. mysql innodb 从 ibd 文件恢复表数据

    最近内部的 mysql 数据库发生了一件奇怪的事,其中有一个表 users625 突然出现问题, 所有对它的操作都报错误 数据表不存在. mysql> select count(*) from ...

  8. 如何批量删除QQ浏览器指定历史记录和导出指定的历史记录

    QQ浏览器的历史记录只有清空历史记录和删除选中项两个功能.有时我不想删除所有的历史记录,只是想删除指定的历史记录保留对自己有用的历史记录,方便自己以后查找.但是删除选中项功能只能一项一项的选择,才能批 ...

  9. 【RL系列】马尔可夫决策过程——状态价值评价与动作价值评价

    请先阅读上两篇文章: [RL系列]马尔可夫决策过程中状态价值函数的一般形式 [RL系列]马尔可夫决策过程与动态编程 状态价值函数,顾名思义,就是用于状态价值评价(SVE)的.典型的问题有“格子世界(G ...

  10. linux递归查找文件内容并替换

    sed -i 's/原字符串/替换后字符串/g' `grep '搜索关键字' -rl /data/目标目录/ --include "*.html"` 上面是递归查找目录中所有的HT ...