Description
Somewhere near the south pole, a number of penguins are standing on a number of ice floes. Being social animals, the penguins would like to get together, all on the same floe. The penguins do not want to get wet, so they have use their limited jump distance to get together by jumping from piece to piece. However, temperatures have been high lately, and the floes are showing cracks, and they get damaged further by the force needed to jump to another floe. Fortunately the penguins are real experts on cracking ice floes, and know exactly how many times a penguin can jump off each floe before it disintegrates and disappears. Landing on an ice floe does not damage it. You have to help the penguins find all floes where they can meet.
A sample layout of ice floes with 3 penguins on them.
Input
On the first line one positive number: the number of testcases, at most 100. After that per testcase:
-
One line with the integer N (1 ≤ N ≤ 100) and a floating-point number D (0 ≤ D ≤ 100 000 ), denoting the number of ice pieces and the maximum distance a penguin can jump.
-
N lines, each line containing xi, yi, ni and mi, denoting for each ice piece its X and Y coordinate, the number of penguins on it and the maximum number of times a penguin can jump off this piece before it disappears ( −10 000 ≤ xi, yi ≤ 10 000 , 0 ≤ ni ≤ 10, 1 ≤ mi ≤ 200).
Output
Per testcase:
- One line containing a space-separated list of 0-based indices of the pieces on which all penguins can meet. If no such piece exists, output a line with the single number −1.
题目大意:有n块浮冰,每块冰上有ni只企鹅,他们最多能跳距离D,现在这些企鹅想在同一块冰上集中,但是呢,冰有裂缝,每块冰只能被企鹅在上面跳走mi次(跳进来和站在上面都不影响),问企鹅们可以集中在哪些浮冰上。
思路:拆点,每个点x拆成x和x',每个x到x'连边,容量为能跳多少次。然后如果i到j的距离不大于D,那么在i'到j连一条边,容量为无穷大。源点S到每一个点x连一条边,容量为有多少只企鹅在x上。最后,枚举每一个点x,x到汇点T连一条边,容量为无穷大,判断最大流是否等于企鹅的数量。
算法正确性说明:如此建图,每只企鹅都从源点开始走到汇点,但每个冰块只能经过cap[x->x']次,保证了企鹅只能从x跳走mi次。
PS:我枚举的时候,只是把前一条边的容量搞成0(要删掉好像好麻烦的样子),再新建一条从枚举点到汇点的边,这样就不用每次都建图了。
PS2:D居然是浮点数……还好没因此WA……
BFS+ISAP(235MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 8 const int MAXN = 222; 9 const int MAXE = MAXN * MAXN * 2; 10 const int INF = 0x3f3f3f3f; 11 12 struct SAP { 13 int head[MAXN], dis[MAXN], gap[MAXN], pre[MAXN], cur[MAXN]; 14 int to[MAXE], next[MAXE], flow[MAXE], cap[MAXE]; 15 int st, ed, n, ecnt; 16 17 void init() { 18 memset(head, 0, sizeof(head)); 19 ecnt = 2; 20 } 21 22 void add_edge(int u, int v, int f) { 23 to[ecnt] = v; cap[ecnt] = f; flow[ecnt] = 0; next[ecnt] = head[u]; head[u] = ecnt++; 24 to[ecnt] = u; cap[ecnt] = 0; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++; 25 //printf("%d->%d cap=%d ", u, v, f); 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 && cap[p ^ 1]) { 38 dis[v] = dis[u] + 1; 39 que.push(v); 40 } 41 } 42 } 43 } 44 45 int Maxflow(int ss, int tt, int nn) { 46 st = ss, ed = tt, n = nn; 47 int ans = 0, minFlow = INF, u; 48 for(int i = 0; i <= n; ++i) { 49 cur[i] = head[i]; 50 gap[i] = 0; 51 } 52 u = pre[st] = st; 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(cap[p] > flow[p] && dis[u] == dis[v] + 1) { 59 flag = true; 60 minFlow = min(minFlow, cap[p] - 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(cap[p] > 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 struct Point { 93 int x, y, n, m; 94 void read() { 95 scanf("%d%d%d%d", &x, &y, &n, &m); 96 } 97 }; 98 99 double dist(const Point &a, const Point &b) { 100 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 101 } 102 103 int n, ss, tt; 104 int ans[110], cnt; 105 double d; 106 Point p[110]; 107 108 void make_graph() { 109 ss = 2 * n + 1, tt = ss + 1; 110 G.init(); 111 for(int i = 1; i <= n; ++i) 112 if(p[i].n) G.add_edge(ss, 2 * i - 1, p[i].n); 113 for(int i = 1; i <= n; ++i) G.add_edge(2 * i - 1, 2 * i, p[i].m); 114 for(int i = 1; i <= n; ++i) { 115 for(int j = 1; j <= n; ++j) { 116 if(i == j || dist(p[i], p[j]) > d) continue; 117 G.add_edge(i * 2, j * 2 - 1, INF); 118 } 119 } 120 } 121 122 int main() { 123 int T; 124 scanf("%d", &T); 125 while(T--) { 126 scanf("%d%lf", &n, &d); 127 for(int i = 1; i <= n; ++i) p[i].read(); 128 int sum = 0; 129 for(int i = 1; i <= n; ++i) sum += p[i].n; 130 make_graph(); 131 cnt = 0; 132 for(int i = 1; i <= n; ++i) { 133 G.add_edge(i * 2 - 1, tt, INF); 134 memset(G.flow, 0, sizeof(G.flow)); 135 if(sum == G.Maxflow(ss, tt, tt)) ans[++cnt] = i - 1; 136 G.cap[G.ecnt - 2] = 0; 137 } 138 if(cnt == 0) puts("-1"); 139 else { 140 for(int i = 1; i < cnt; ++i) printf("%d ", ans[i]); 141 printf("%d ", ans[cnt]); 142 } 143 } 144 }