码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-10-05 10:26:47      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:

                        The Glorious Karlutka River =)

Time Limit:500MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u

Appoint description:

Description



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

Sample Input

sample input
sample output
3 10 3 7
0 2 2
4 2 2
2 4 3
6

 

sample input
sample output
3 10 3 8
0 2 2
4 2 2
2 4 3
IMPOSSIBLE

 

题意:

给出一条河,宽为W,并建立坐标系,河沿着x轴流动。从原点开始。宽为y轴。

现在给出河上的N个点的坐标和容量,通过这些点可以过河,已知有M个人。每个人每次可以往任意方向跳D米。

每次跳花费1秒。问最少多少时间能使全部人过河。如果不可能则输出“IMPOSSIBLE”。

 

思路:

首先以游客在的河岸为源点,对岸为汇点。

对于每个点容量的限制,需要拆点,把每个点i拆成点i和点i,中间连接一条容量为ci的边。

因为加入了时间限制,所以要按时间将每个石头拆点。

可以知道如果有N个石头和M个人,如果能够过河,最多花费的时间为N+M。所以从1开始枚举T一直到N+M。

T=1的时候,将离游客所在的河岸距离<=D的石子i与汇点连边,容量为正无穷。

T>1的时候,仍将离游客所在的河岸距离<=D的石子i与汇点连边,容量为正无穷。

需要注意的是,应该此时将T-1时刻离对岸距离<=D的石子i与汇点连边,容量为正无穷。表示的是T-1时刻在第i个石头上,花了一秒跳到了对岸,此时时刻为T。

并且将T-1时刻和T时刻距离小于等于D的石头连边,表示的是T-1时刻在i个石头上,花了一秒跳到了j个石头,此时时刻为T。容量为正无穷。

对每秒求最大流,累加每秒钟通过的人数和,当人数>=M时则跳出。

 

  1 //#include <bits/stdc++.h>
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <string>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 using namespace std;
 10 #define maxn 10010
 11 const int inf = 0x3f3f3f3f;
 12 int N, M, D, W;
 13 struct Edge
 14 {
 15     int from, to, cap, flow;
 16     Edge(int f, int t, int c, int fl)
 17     {
 18         from = f; to = t; cap = c; flow = fl;
 19     }
 20 };
 21 struct Piles
 22 {
 23     double x, y;
 24     int c;
 25     Piles(double xx, double yy, int cc)
 26     {
 27         x = xx; y = yy; c = cc;
 28     }
 29     Piles(){}
 30 }p[55];
 31 vector <Edge> edges;
 32 vector <int> G[maxn];
 33 int n, m, s, t;
 34 void AddEdge(int from, int to, int cap)
 35 {
 36     edges.push_back(Edge(from, to, cap, 0));
 37     edges.push_back(Edge(to, from, 0, 0));
 38     m = edges.size();
 39     G[from].push_back(m-2);
 40     G[to].push_back(m-1);
 41 }
 42 int vis[maxn], cur[maxn], d[maxn];
 43 int cntnow;
 44 bool bfs()
 45 {
 46     memset(vis, 0, sizeof(vis));
 47     d[s] = 0; vis[s] = 1;
 48     queue <int> q;
 49     q.push(s);
 50     while(!q.empty())
 51     {
 52         int u = q.front(); q.pop();
 53         for(int i = 0; i < G[u].size(); i++)
 54         {
 55             Edge &e = edges[G[u][i]];
 56             if(!vis[e.to] && e.cap > e.flow)
 57             {
 58                 vis[e.to] = 1;
 59                 d[e.to] = d[u]+1;
 60                 q.push(e.to);
 61             }
 62         }
 63     }
 64     return vis[t];
 65 }
 66 int dfs(int x, int a)
 67 {
 68     if(x == t || a == 0) return a;
 69     int flow = 0, f;
 70     for(int &i = cur[x]; i < G[x].size(); i++)
 71     {
 72         Edge &e = edges[G[x][i]];
 73         if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap-e.flow, a))) > 0)
 74         {
 75             e.flow += f;
 76             edges[G[x][i]^1].flow -= f;
 77             flow += f;
 78             a -= f;
 79             if(a == 0) break;
 80         }
 81     }
 82     return flow;
 83 }
 84 int MaxFlow()
 85 {
 86     int flow = 0;
 87     while(bfs())
 88     {
 89         memset(cur, 0, sizeof(cur));
 90         flow += dfs(s, inf);
 91     }
 92     return flow;
 93 }
 94 int mp[55][55];
 95 double dist(Piles p1, Piles p2)
 96 {
 97     return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
 98 }
 99 int main()
100 {
101     while(~scanf("%d%d%d%d", &N, &M, &D, &W))
102     {
103         edges.clear();
104         for(int i = 0; i <= N*2*(N+M)+1; i++) G[i].clear();
105         for(int i = 1; i <= N; i++)
106         {
107             scanf("%lf%lf%d", &p[i].x, &p[i].y, &p[i].c);
108         }
109         if(D >= W)
110         {
111             printf("1\n"); continue;
112         }
113         memset(mp, 0, sizeof(mp));
114         for(int i = 1; i <= N; i++)
115         {
116             for(int j = 1; j <= N; j++)
117             {
118                 if(dist(p[i], p[j]) <= D) mp[i][j] = mp[j][i] = 1;
119             }
120         }
121 
122         s = 0; t = N*2*(N+M)+1;
123         for(int i = 1; i <= N; i++)
124         {
125             if(p[i].y <= D) AddEdge(s, i, inf);
126             AddEdge(i, i+N, p[i].c);
127         }
128 
129         bool flag = false;
130         int sum = 0;
131         for(int T = 2; T <= N+M; T++)
132         {
133             for(int i = 1; i <= N; i++)
134             {
135                 if(p[i].y <= D) AddEdge(s, (T-1)*2*N+i, inf);
136                 if(W-p[i].y <= D) AddEdge((T-2)*2*N+i+N, t, inf);
137                 AddEdge((T-1)*2*N+i, (T-1)*2*N+i+N, p[i].c);
138 
139                 for(int j = 1; j <= N; j++)
140                 {
141                     if(mp[i][j])
142                     {
143                         AddEdge((T-2)*2*N+j+N, (T-1)*2*N+i, inf);
144                     }
145                 }
146             }
147             int flow = MaxFlow();
148             sum += flow;
149             if(sum >= M)
150             {
151                 flag = true;
152                 printf("%d\n", T);
153                 break;
154             }
155         }
156         if(flag == false)
157         {
158             printf("IMPOSSIBLE\n");
159         }
160 
161     }
162     return 0;
163 }

 

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

标签:

原文地址:http://www.cnblogs.com/titicia/p/4855355.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!