【SGU438】The Glorious Karlutka River =) 分层图最大流

来源:互联网 发布:java unsafe类 编辑:程序博客网 时间:2024/06/03 11:18

A group of M tourists 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.

A 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 (Xi, Yi) 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 Y coordinate 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 tourists M (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 < Yi < W, 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.

Example(s)

sample input3 10 3 70 2 24 2 22 4 3sample output6sample input3 10 3 80 2 24 2 22 4 3sample outputIMPOSSIBLE

有一条河,宽为w,有n个垃圾袋在河上,m个人想踩垃圾袋过河。第i个垃圾袋同一时刻只能承载ci人,每人一秒钟只能跳一下,最远跳跃距离是d。现在给你n个垃圾袋的坐标,m个人想从直线y=0以下跳到y=w以上,问全部通过的最少时间。

每个垃圾袋拆点,点容量放在边上,然后按时间拆点。注意源点要向各个时间线的所有能到达的石头连边,汇点也是。

有一个疑问,为什么dfs判断可行之后还有可能无法全部通过?为什么在ans很大之后无解就要IMPOSSIBLE??

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<queue>#include<cmath>using namespace std;const int INF = 1000000010;const int SZ = 2000010;int n;int head[SZ],nxt[SZ],tot = 1;struct edge{    int t,d;}l[SZ];void build(int f,int t,int d){    l[++ tot].t = t;    l[tot].d = d;    nxt[tot] = head[f];    head[f] = tot;}void insert(int f,int t,int d){    build(f,t,d); build(t,f,0);}int deep[SZ];queue<int> q;bool bfs(int s,int e){    memset(deep,0,sizeof(deep));    deep[s] = 1;    while(q.size()) q.pop();    q.push(s);    while(q.size())    {        int u = q.front(); q.pop();        for(int i = head[u];i;i = nxt[i])        {            int v = l[i].t;            if(!deep[v] && l[i].d)            {                deep[v] = deep[u] + 1;                q.push(v);                if(v == e) return true;            }        }    }    return false;}int dfs(int u,int flow,int e){    if(u == e || flow == 0) return flow;    int rest = flow;    for(int i = head[u];i;i = nxt[i])    {        int v = l[i].t;        if(deep[v] == deep[u] + 1 && l[i].d)        {            int f = dfs(v,min(l[i].d,rest),e);            if(f > 0)            {                l[i].d -= f;                l[i ^ 1].d += f;                rest -= f;                if(rest == 0) break;            }            else deep[v] = 0;        }    }    return flow - rest;}int dinic(int s,int e){    int ans = 0;    while(bfs(s,e)) ans += dfs(s,INF,e);    return ans;}double getdist(int x1,int y1,int x2,int y2){    double a = x1 - x2;    double b = y1 - y2;    return sqrt(a * a + b * b);}int getnode(int p,int ans){    return p + ans * 2 * n;}int xx[SZ],yy[SZ],cc[SZ];bool dist[233][233];bool vis[SZ];int m,d,w;bool dfs(int u){    if(cc[u] == 0) return false;    if(w - yy[u] <= d) return true;    vis[u] = 1;    for(int i = 1;i <= n;i ++)        if(!vis[i] && dist[i][u] <= d)            if(dfs(i)) return true;    return false;}bool check(){    for(int i = 1;i <= n;i ++)        if(yy[i] <= d)             if(dfs(i)) return true;    return false;}int main(){    scanf("%d%d%d%d",&n,&m,&d,&w);    for(int i = 1;i <= n;i ++)        scanf("%d%d%d",&xx[i],&yy[i],&cc[i]);    for(int i = 1;i <= n;i ++)        for(int j = 1;j <= n;j ++)            dist[i][j] = getdist(xx[i],yy[i],xx[j],yy[j]) <= d ? 1 : 0;    if(d >= w) { puts("1"); return 0; }    if(!check()) { puts("IMPOSSIBLE"); return 0; }    int s = 0,e = 200000;    for(int i = 1;i <= n;i ++)        insert(i,i + n,cc[i]);/*  for(int i = 1;i <= n;i ++)    {        if(yy[i] <= d)            insert(s,i,INF);        if(w - yy[i] <= d)            insert(i + n,e,INF);    }*/    int ans = 0,sum = 0;    while(ans < 233)    {        sum += dinic(s,e);        if(sum >= m) break;        for(int i = 1;i <= n;i ++)            for(int j = 1;j <= n;j ++)                if(i != j && dist[i][j])                    insert(getnode(i + n,ans),getnode(j,ans + 1),INF);        for(int i = 1;i <= n;i ++)            insert(getnode(i,ans + 1),getnode(i + n,ans + 1),cc[i]);        for(int i = 1;i <= n;i ++)        {            if(yy[i] <= d)                insert(s,getnode(i,ans + 1),INF);            if(w - yy[i] <= d)                insert(getnode(i + n,ans + 1),e,INF);        }           ans ++;     }    if(ans < 233) printf("%d",ans + 1);    else puts("IMPOSSIBLE");    return 0;}
0 0