标签:
The Glorious Karlutka River =)
Time Limit:500MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u
Description
Input
Output
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