把这题当动态流入门题来做了。
网上的题解都已经说的很清楚了。这里再强调一下几个特殊的点。
- 当跳动距离大于河宽时,直接输出1
- 每个点都需要拆点,当我们在两个不同点之间连边时,需要从一个点的上一秒拆出来的点走到另一点的这一秒的点。
- 连终点是把上一秒的这个点拆出来的点和终点相连,而和起点连的是这一秒的点。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int MAXN = 3e5;
const double eps = 1e-8;
const int MAXM = 1e7;
const int INF = 0x3f3f3f3f;
int head[MAXN],dis[MAXN],tol,n,m,w,d,x[MAXN],y[MAXN],lim[MAXN],src,det;
struct Edge
{
int to,cap,flow,nex;
Edge(int to,int cap,int flow,int nex):to(to),cap(cap),flow(flow),nex(nex) {}
Edge() {}
}edge[MAXM];
void init()
{
memset(head,-1,sizeof head);
tol=0;
}
void addedge(int u,int v,int cap)
{
edge[tol]=Edge(v,cap,0,head[u]); head[u]=tol++;
edge[tol]=Edge(u,0,0,head[v]); head[v]=tol++;
}
int dcmp(double a,double b)
{
if (a-b>eps) return 1;
if (a-b<-eps) return -1;
return 0;
}
double dist(int i,int j)
{
return sqrt(1.0*(x[i]-x[j])*(x[i]-x[j]) + 1.0*(y[i]-y[j])*(y[i]-y[j]));
}
bool bfs(int s,int t)
{
memset(dis,-1,sizeof dis);
dis[s]=0;
queue<int> que;
que.push(s);
while (!que.empty())
{
int u=que.front();que.pop();
for (int i=head[u];~i;i=edge[i].nex)
{
int v=edge[i].to;
if (dis[v]==-1 &&edge[i].cap-edge[i].flow)
{
dis[v]=dis[u]+1;
if (v==t) return true;
que.push(v);
}
}
}
return false;
}
int dfs(int u,int t,int cap)
{
if (u==t) return cap;
int flow=0,f;
for (int i=head[u];~i;i=edge[i].nex)
{
int v=edge[i].to;
if (dis[v]==dis[u]+1 && edge[i].cap>edge[i].flow)
{
f=dfs(v,t,min(cap-flow,edge[i].cap-edge[i].flow));
edge[i].flow += f;
edge[i^1].flow -=f;
flow +=f ;
if (cap == flow )break;
}
}
if (!flow) dis[u]=-1;
return flow;
}
int dicnic(int s,int t)
{
int flow=0,a;
while (bfs(s,t))
while ( (a=dfs(s,t,INF)) >0)
flow+=a;
return flow;
}
int main()
{
src=0;det=6000;
while (scanf("%d%d%d%d",&n,&m,&d,&w)!=EOF)
{
int cnt=0;
init();
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&lim[i]);
}
if (d>=w)
{
cout<<"1"<<endl;
continue;
}
int flow=0,t;
for (t=1;t<=n+m;t++)
{
for (int i=1;i<=n;i++)
{
if (y[i]<=d)
addedge(0,t*200+i,INF);
if (w-y[i]<=d)
addedge((t-1)*200+i+50,det,INF);
for (int j=1;j<=n;j++)
if (i!=j && dcmp(dist(i,j),d)<=0)
addedge((t-1)*200+i+50,t*200+j,INF);
addedge(t*200+i,t*200+i+50,lim[i]);
}
flow += dicnic(src,det);
// cout<<t<<" "<<flow<<endl;
if (flow >= m) break;
}
if (flow < m)
printf("IMPOSSIBLE\n");
else
printf("%d\n",t);
}
return 0;
}