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

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

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

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

一直增加层数,直到最大流达到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. [BZOJ3167][HEOI2013]SAO[树dp+组合数学]

    题意 给定 \(n\) 个节点和 \(n-1\) 个限制,每个节点有一个权值,每个限制形如:\(a_i< a_j\) ,问有多少个 \(1\) 到 \(n\) 排列满足要求. \(n\leq 1 ...

  2. 对ThreadLocal的源码解读

    早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 功能 ...

  3. jQuery js 格式化数字

    写程序与的时候,有些地方需要js或者jQuery取值,然后将50000000.00格式化成50,000,000.00这种形式: 首先创建formatCurrency.js,代码如下: function ...

  4. Navigation - How to define the structure of the navigation tree via the NavigationItemAttribute

    In the meantime, you should use the Model Editor to create such a navigation structure. There are se ...

  5. Discuz x3.2利用阿里云cdn处理https访问亲测教程

    第一步配置cdn和https 1.首先去阿里云.腾讯云.七牛云等申请免费https证书 2.虚拟主机是不能直接支持https的,需要cdn处理后才可以,并且端口是80 3.开启cdn加速处理,(买一个 ...

  6. hdu2544最短路(dijkstra)

    传送门 dijkstra #include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; ; int dist ...

  7. Selenium+Python自动化测试学习问题总结笔记

    1.问题描述:不能导入自定义类 错误内容:This inspection detects names that should resolve but don't. Due to dynamic dis ...

  8. L2-016 愿天下有情人都是失散多年的兄妹

    L2-016 愿天下有情人都是失散多年的兄妹 (25 分)   呵呵.大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人.父母.祖父母.曾祖父母.高祖父母)则不可通婚.本题就请你 ...

  9. C#多线程的几种使用

    参见链接   :http://www.jb51.net/article/46234.htm

  10. 六度空间(MOOC)

    六度空间: “六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论.这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五 ...