SGU 438 The Glorious Karlutka River =) 动态流 最大流

把这题当动态流入门题来做了。
网上的题解都已经说的很清楚了。这里再强调一下几个特殊的点。

  1. 当跳动距离大于河宽时,直接输出1
  2. 每个点都需要拆点,当我们在两个不同点之间连边时,需要从一个点的上一秒拆出来的点走到另一点的这一秒的点。
  3. 连终点是把上一秒的这个点拆出来的点和终点相连,而和起点连的是这一秒的点。
#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;
}

猜你喜欢

转载自blog.csdn.net/z631681297/article/details/77968516
sgu