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 "); 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 ", T); 153 break; 154 } 155 } 156 if(flag == false) 157 { 158 printf("IMPOSSIBLE "); 159 } 160 161 } 162 return 0; 163 }