SGU 438 The Glorious Karlutka River =)(最大流)

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. 
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 ( XiYi) 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 Ycoordinate 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 touristM (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 < YiW, 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.
 

题目大意:M 个人要过河,,河宽为 W。河上有N个垃圾,给出垃圾的坐标以及垃圾能同时容纳的人数,现在这 M 个人一下能跳距离D,问最少需要多少时间才可以使所有人到达对岸。跳一步一秒。 (开始人都在 X 轴上.对岸可以看为 Y =W 的一条直线)

思路:二分答案,判定性的最大流。最少用时间1到达对岸,最后用时间N+M到达对岸(假设要经过全部垃圾并且全部垃圾都只能站一个人)。假设现在二分的答案为mid,那么对于每个垃圾分成mid-1份,每份代表一个时间,再每个时间分成两份P、P'。如果从X轴能走到某点P,那么对所有时间,S连一条边到P。如果从某点P能走到对岸,那么对所有时间,P'连一条边到T。然后对所有时间每个点P连一条边到P',容量为该点能同时站多少人。最后所有距离在D以内的,对每个时间t,连边(P,t)→(Q,t+1),(Q,t)→(P,t+1)。最大流即为用mid的时间能过去多少人。二分答案即可。这种做法正确是因为:每个点的时间t只能走到t+1的时间,而在每个时间里通过某一点的流量不大于该点的容量,在任何时刻都能从S出发和到达T。

另外

 

SAP(62MS):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int MAXN = 55 * 105 * 2;
  8 const int MAXE = MAXN * 500;
  9 const int INF = 0x7fff7fff;
 10 
 11 struct SAP {
 12     int vis[MAXN], head[MAXN];
 13     int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
 14     int to[MAXE], flow[MAXE], next[MAXE];
 15     int ecnt, st, ed;
 16 
 17     void init(int ss, int tt) {
 18         memset(head, 0, sizeof(head));
 19         ecnt = 2;
 20         st = ss; ed = tt;
 21     }
 22 
 23     void addEdge(int u,int v,int f) {
 24         to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
 25         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
 26     }
 27 
 28     int Max_flow() {
 29         int ans = 0, minFlow = INF, n = ed, u;
 30         for (int i = 0; i <= n; ++i){
 31             cur[i] = head[i];
 32             gap[i] = dis[i] = 0;
 33         }
 34         u = pre[st] = st;
 35         gap[0] = n;
 36         while (dis[st] < n){
 37             bool flag = false;
 38             for (int &p = cur[u]; p; p = next[p]){
 39                 int v = to[p];
 40                 if (flow[p] > 0 && dis[u] == dis[v] + 1){
 41                     flag = true;
 42                     minFlow = min(minFlow, flow[p]);
 43                     pre[v] = u;
 44                     u = v;
 45                     if(u == ed){
 46                         ans += minFlow;
 47                         while (u != st){
 48                             u = pre[u];
 49                             flow[cur[u]] -= minFlow;
 50                             flow[cur[u] ^ 1] += minFlow;
 51                         }
 52                         minFlow = INF;
 53                     }
 54                     break;
 55                 }
 56             }
 57             if (flag) continue;
 58             int minDis = n-1;
 59             for (int p = head[u]; p; p = next[p]){
 60                 int v = to[p];
 61                 if (flow[p] && dis[v] < minDis){
 62                     minDis = dis[v];
 63                     cur[u] = p;
 64                 }
 65             }
 66             if (--gap[dis[u]] == 0) break;
 67             gap[dis[u] = minDis+1]++;
 68             u = pre[u];
 69         }
 70         return ans;
 71     }
 72 } G;
 73 
 74 const int MAX = 55;
 75 
 76 struct Point {
 77     int x, y, c;
 78 };
 79 
 80 int dis2(const Point &a, const Point &b) {
 81     int xx = a.x - b.x, yy = a.y - b.y;
 82     return xx * xx + yy * yy;
 83 }
 84 
 85 int n, m, d, w;
 86 Point rub[MAX];
 87 
 88 #define FOR(i, s, t) for(int i = s; i <= t; ++i)
 89 #define get_num(i, t) ((i - 1) * 2 * (mid - 1) + 2 * (t - 1) + 1)
 90 
 91 void solve() {
 92     int left = 1, right = n + m + 1;
 93     while(left < right) {
 94         int mid = (left + right) >> 1;
 95         int ss = n * (mid - 1) * 2 + 1, st = ss + 1, tt = ss + 2;
 96         G.init(st, tt);
 97         G.addEdge(st, ss, m);
 98         FOR(i, 1, n) {
 99             if(rub[i].y <= d) {
100                 FOR(t, 1, mid - 1) G.addEdge(ss, get_num(i, t), INF);
101             }
102             if(rub[i].y + d >= w) {
103                 FOR(t, 1, mid - 1) G.addEdge(get_num(i, t) + 1, tt, INF);
104             }
105         }
106         FOR(i, 1, n) FOR(t, 1, mid - 1) {
107             int num = get_num(i, t);
108             G.addEdge(num, num + 1, rub[i].c);
109             if(t < mid - 1) G.addEdge(num + 1, num + 2, INF);
110         }
111         FOR(i, 1, n) FOR(j, 1, n) {
112             if(i == j || dis2(rub[i], rub[j]) > d * d) continue;
113             FOR(t, 1, mid - 2) G.addEdge(get_num(i, t) + 1, get_num(j, t + 1), INF);
114         }
115         int ans = G.Max_flow();
116         if(ans < m) left = mid + 1;
117         else right = mid;
118         //printf("%d %d\n", mid, ans); system("pause");
119     }
120     if(right == n + m + 1) puts("IMPOSSIBLE");
121     else printf("%d\n", right);
122 }
123 
124 int main() {
125     scanf("%d%d%d%d", &n, &m, &d, &w);
126     FOR(i, 1, n) scanf("%d%d%d", &rub[i].x, &rub[i].y, &rub[i].c);
127     FOR(i, 1, n) if(rub[i].c > m) rub[i].c = m;
128     if(w <= d) printf("1\n");
129     else solve();
130 }
View Code

DINIC(15MS):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int MAXN = 55 * 105 * 2;
  8 const int MAXE = MAXN * 500;
  9 const int INF = 0x7fff7fff;
 10 
 11 struct Dinic {
 12     int n, m, st, ed, ecnt;
 13     int vis[MAXN], head[MAXN];
 14     int cur[MAXN], d[MAXN];
 15     int to[MAXE], next[MAXE], flow[MAXE];
 16 
 17     void init(){
 18         memset(head,0,sizeof(head));
 19         ecnt = 2;
 20     }
 21 
 22     void addEdge(int u,int v,int f) {
 23         to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
 24         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
 25     }
 26 
 27     bool bfs() {
 28         memset(vis, 0, sizeof(vis));
 29         queue<int> que; que.push(st);
 30         d[st] = 0; vis[st] = true;
 31         while(!que.empty()){
 32             int u = que.front(); que.pop();
 33             for(int p = head[u]; p; p = next[p]){
 34                 int v = to[p];
 35                 if (!vis[v] && flow[p] > 0){
 36                     vis[v] = 1;
 37                     d[v] = d[u] + 1;
 38                     que.push(v);
 39                     if(v == ed) return true;
 40                 }
 41             }
 42         }
 43         return vis[ed];
 44     }
 45 
 46     int dfs(int u, int a) {
 47         if(u == ed || a == 0) return a;
 48         int outflow = 0, f;
 49         for(int &p = cur[u]; p; p = next[p]){
 50             int v = to[p];
 51             if(d[u] + 1 == d[v] && (f = dfs(v, min(a, flow[p]))) > 0){
 52                 flow[p] -= f;
 53                 flow[p ^ 1] += f;
 54                 outflow += f;
 55                 a -= f;
 56                 if(a == 0) break;
 57             }
 58         }
 59         return outflow;
 60     }
 61 
 62     int Maxflow(int ss, int tt, int nn) {
 63         st = ss; ed = tt;
 64         int ans = 0;
 65         while(bfs()){
 66             for(int i = 0; i <= ed; ++i) cur[i] = head[i];
 67             ans += dfs(st, INF);
 68         }
 69         return ans;
 70     }
 71 } G;
 72 
 73 const int MAX = 55;
 74 
 75 struct Point {
 76     int x, y, c;
 77 };
 78 
 79 int dis2(const Point &a, const Point &b) {
 80     int xx = a.x - b.x, yy = a.y - b.y;
 81     return xx * xx + yy * yy;
 82 }
 83 
 84 int n, m, d, w;
 85 Point rub[MAX];
 86 
 87 #define FOR(i, s, t) for(int i = s; i <= t; ++i)
 88 #define get_num(i, t) ((i - 1) * 2 * (mid - 1) + 2 * (t - 1) + 1)
 89 
 90 void solve() {
 91     int left = 1, right = n + m + 1;
 92     while(left < right) {
 93         int mid = (left + right) >> 1;
 94         int ss = n * (mid - 1) * 2 + 1, st = ss + 1, tt = ss + 2;
 95         G.init();
 96         G.addEdge(st, ss, m);
 97         FOR(i, 1, n) {
 98             if(rub[i].y <= d) {
 99                 FOR(t, 1, mid - 1) G.addEdge(ss, get_num(i, t), INF);
100             }
101             if(rub[i].y + d >= w) {
102                 FOR(t, 1, mid - 1) G.addEdge(get_num(i, t) + 1, tt, INF);
103             }
104         }
105         FOR(i, 1, n) FOR(t, 1, mid - 1) {
106             int num = get_num(i, t);
107             G.addEdge(num, num + 1, rub[i].c);
108             if(t < mid - 1) G.addEdge(num + 1, num + 2, INF);
109         }
110         FOR(i, 1, n) FOR(j, 1, n) {
111             if(i == j || dis2(rub[i], rub[j]) > d * d) continue;
112             FOR(t, 1, mid - 2) G.addEdge(get_num(i, t) + 1, get_num(j, t + 1), INF);
113         }
114         int ans = G.Maxflow(st, tt, tt);
115         if(ans < m) left = mid + 1;
116         else right = mid;
117         //printf("%d %d\n", mid, ans); system("pause");
118     }
119     if(right == n + m + 1) puts("IMPOSSIBLE");
120     else printf("%d\n", right);
121 }
122 
123 int main() {
124     scanf("%d%d%d%d", &n, &m, &d, &w);
125     FOR(i, 1, n) scanf("%d%d%d", &rub[i].x, &rub[i].y, &rub[i].c);
126     FOR(i, 1, n) if(rub[i].c > m) rub[i].c = m;
127     if(w <= d) printf("1\n");
128     else solve();
129 }
View Code

BFS+ISAP(15MS):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int MAXN = 53 * 105 * 2;
  8 const int MAXE = MAXN * 100;
  9 const int INF = 0x7fff7fff;
 10 
 11 struct SAP {
 12     int head[MAXN];
 13     int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
 14     int to[MAXE], flow[MAXE], next[MAXE];
 15     int ecnt, st, ed, n;
 16 
 17     void init(int ss, int tt, int nn) {
 18         memset(head, 0, sizeof(head));
 19         ecnt = 2;
 20         st = ss; ed = tt; n = nn;
 21     }
 22 
 23     void addEdge(int u,int v,int f) {
 24         to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
 25         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
 26     }
 27 
 28     void bfs() {
 29         memset(dis, 0x3f, sizeof(dis));
 30         queue<int> que; que.push(ed);
 31         dis[ed] = 0;
 32         while(!que.empty()) {
 33             int u = que.front(); que.pop();
 34             ++gap[dis[u]];
 35             for(int p = head[u]; p; p = next[p]) {
 36                 int v = to[p];
 37                 if (dis[v] > n && flow[p ^ 1] > 0) {
 38                     dis[v] = dis[u] + 1;
 39                     que.push(v);
 40                 }
 41             }
 42         }
 43     }
 44 
 45     int Max_flow() {
 46         int ans = 0, minFlow = INF,  u;
 47         for (int i = 0; i <= n; ++i){
 48             cur[i] = head[i];
 49             gap[i] = dis[i] = 0;
 50         }
 51         u = pre[st] = st;
 52         //gap[0] = n;
 53         bfs();
 54         while (dis[st] < n){
 55             bool flag = false;
 56             for (int &p = cur[u]; p; p = next[p]){
 57                 int v = to[p];
 58                 if (flow[p] > 0 && dis[u] == dis[v] + 1){
 59                     flag = true;
 60                     minFlow = min(minFlow, flow[p]);
 61                     pre[v] = u;
 62                     u = v;
 63                     if(u == ed){
 64                         ans += minFlow;
 65                         while (u != st){
 66                             u = pre[u];
 67                             flow[cur[u]] -= minFlow;
 68                             flow[cur[u] ^ 1] += minFlow;
 69                         }
 70                         minFlow = INF;
 71                     }
 72                     break;
 73                 }
 74             }
 75             if (flag) continue;
 76             int minDis = n-1;
 77             for (int p = head[u]; p; p = next[p]){
 78                 int v = to[p];
 79                 if (flow[p] && dis[v] < minDis){
 80                     minDis = dis[v];
 81                     cur[u] = p;
 82                 }
 83             }
 84             if (--gap[dis[u]] == 0) break;
 85             gap[dis[u] = minDis+1]++;
 86             u = pre[u];
 87         }
 88         return ans;
 89     }
 90 } G;
 91 
 92 const int MAX = 55;
 93 
 94 struct Point {
 95     int x, y, c;
 96 };
 97 
 98 int dis2(const Point &a, const Point &b) {
 99     int xx = a.x - b.x, yy = a.y - b.y;
100     return xx * xx + yy * yy;
101 }
102 
103 int n, m, d, w;
104 Point rub[MAX];
105 
106 #define FOR(i, s, t) for(int i = s; i <= t; ++i)
107 #define get_num(i, t) ((i - 1) * 2 * (mid - 1) + 2 * (t - 1) + 1)
108 
109 void solve() {
110     int left = 1, right = n + m + 1;
111     while(left < right) {
112         int mid = (left + right) >> 1;
113         int ss = n * (mid - 1) * 2 + 1, st = ss + 1, tt = ss + 2;
114         G.init(st, tt, tt);
115         G.addEdge(st, ss, m);
116         FOR(i, 1, n) {
117             if(rub[i].y <= d) {
118                 FOR(t, 1, mid - 1) G.addEdge(ss, get_num(i, t), INF);
119             }
120             if(rub[i].y + d >= w) {
121                 FOR(t, 1, mid - 1) G.addEdge(get_num(i, t) + 1, tt, INF);
122             }
123         }
124         FOR(i, 1, n) FOR(t, 1, mid - 1) {
125             int num = get_num(i, t);
126             G.addEdge(num, num + 1, rub[i].c);
127             if(t < mid - 1) G.addEdge(num + 1, num + 2, INF);
128         }
129         FOR(i, 1, n) FOR(j, 1, n) {
130             if(i == j || dis2(rub[i], rub[j]) > d * d) continue;
131             FOR(t, 1, mid - 2) G.addEdge(get_num(i, t) + 1, get_num(j, t + 1), INF);
132         }
133         int ans = G.Max_flow();
134         if(ans < m) left = mid + 1;
135         else right = mid;
136         //printf("%d %d\n", mid, ans); system("pause");
137     }
138     if(right == n + m + 1) puts("IMPOSSIBLE");
139     else printf("%d\n", right);
140 }
141 
142 int main() {
143     scanf("%d%d%d%d", &n, &m, &d, &w);
144     FOR(i, 1, n) scanf("%d%d%d", &rub[i].x, &rub[i].y, &rub[i].c);
145     FOR(i, 1, n) if(rub[i].c > m) rub[i].c = m;
146     if(w <= d) printf("1\n");
147     else solve();
148 }
View Code

 

posted @ 2013-08-06 20:31  Oyking  阅读(446)  评论(0编辑  收藏  举报