March of the Penguins | ||||||
| ||||||
Description | ||||||
Somewhere near the south pole, a number of penguins Fortunately the penguins are real experts on
| ||||||
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 ≤ 100000), 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. | ||||||
Sample Input | ||||||
2 5 3.5 1 1 1 1 2 3 0 1 3 5 1 1 5 1 1 1 5 4 0 1 3 1.1 -1 0 5 10 0 0 3 9 2 0 1 1 | ||||||
Sample Output | ||||||
1 2 4 -1 | ||||||
Source | ||||||
NWERC2007 |
大意:有n块冰块,每块冰块上有一定数量企鹅,并且有一定的跳跃次数(jump off)超过这个次数冰块就会碎掉
告诉每块冰块的企鹅数目和跳跃次数,问那些冰块能使所有的企鹅都到达(冰块编号从零开始)
模型:
1、首先这是一个无向图, 所以冰块之间建立路径的时候要件两条路
2、节点有权值(跳跃次数) 所以要拆点
思路:
冰块拆点之间的权值是跳跃次数
若两冰块之间能到达则建立两条路径(s1,t1)(s2,t2)的话 则由t1指向s2 由t2指向s1,权值为无穷
超级源点跟每块冰块的s建立一条路径,权值为企鹅数量
最后依次枚举每个点做汇点的最大流是否等于企鹅数量即可
代码:
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <vector>
5 #include <queue>
6 #include <cmath>
7 using namespace std;
8
9 const int maxn = 505;
10 const int INF = 10000000;
11
12 struct Point{
13 int x, y, ni, mi;
14 }point[maxn];
15
16
17 struct Edge
18 {
19 int from, to, cap, flow, flow2;
20 };
21
22 struct ISAP {
23 int n, m, s, t;
24 vector<Edge> edges;
25 vector<int> G[maxn];
26 bool vis[maxn];
27 int d[maxn];
28 int cur[maxn];
29 int p[maxn];
30 int num[maxn];
31
32 void AddEdge(int from, int to, int cap) {
33 edges.push_back((Edge){from, to, cap, 0, 0});
34 edges.push_back((Edge){to, from, 0, 0, 0});
35 m = edges.size();
36 G[from].push_back(m-2);
37 G[to].push_back(m-1);
38 }
39
40 void init() {
41 for(int i = 0; i < m; i++){
42 edges[i].flow = edges[i].flow2;
43 }
44 }
45
46 bool BFS() {
47 memset(vis, 0, sizeof(vis));
48 queue<int> Q;
49 Q.push(t);
50 vis[t] = 1;
51 d[t] = 0;
52 while(!Q.empty()) {
53 int x = Q.front(); Q.pop();
54 for(int i = 0; i < G[x].size(); i++) {
55 Edge& e = edges[G[x][i]^1];
56 if(!vis[e.from] && e.cap > e.flow) {
57 vis[e.from] = 1;
58 d[e.from] = d[x] + 1;
59 Q.push(e.from);
60 }
61 }
62 }
63 return vis[s];
64 }
65
66 void ClearAll(int n) {
67 this->n = n;
68 for(int i = 0; i < n; i++) G[i].clear();
69 edges.clear();
70 }
71
72 int Augment() {
73 int x = t, a = INF;
74 while(x != s) {
75 Edge& e = edges[p[x]];
76 a = min(a, e.cap-e.flow);
77 x = edges[p[x]].from;
78 }
79 x = t;
80 while(x != s) {
81 edges[p[x]].flow += a;
82 edges[p[x]^1].flow -= a;
83 x = edges[p[x]].from;
84 }
85 return a;
86 }
87
88 int MaxFlow(int s, int t, int need) {
89 this->s = s; this->t = t;
90 int flow = 0;
91 BFS();
92 memset(num, 0, sizeof(num));
93 for(int i = 0; i < n; i++) num[d[i]]++;
94 int x = s;
95 memset(cur, 0, sizeof(cur));
96 while(d[s] < n) {
97 if(x == t) {
98 flow += Augment();
99 if(flow >= need) return flow;
100 x = s;
101 }
102 int ok = 0;
103 for(int i = cur[x]; i < G[x].size(); i++) {
104 Edge& e = edges[G[x][i]];
105 if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance
106 ok = 1;
107 p[e.to] = G[x][i];
108 cur[x] = i;
109 x = e.to;
110 break;
111 }
112 }
113 if(!ok) {
114 int m = n-1;
115 for(int i = 0; i < G[x].size(); i++) {
116 Edge& e = edges[G[x][i]];
117 if(e.cap > e.flow) m = min(m, d[e.to]);
118 }
119 if(--num[d[x]] == 0) break;
120 num[d[x] = m+1]++;
121 cur[x] = 0;
122 if(x != s) x = edges[p[x]].from;
123 }
124 }
125 return flow;
126 }
127 };
128
129
130 ISAP g;
131
132 double get_dist(Point p1, Point p2) {
133 return sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) );
134 }
135
136 int main() {
137 int t;
138 int n; double d;
139 // freopen("a.txt","r",stdin);
140 scanf("%d",&t);
141 while(t--) {
142 scanf("%d %lf",&n, &d);
143 int sum = 0;
144 for(int i = 0; i < n; i++) {
145 scanf("%d %d %d %d",&point[i].x, &point[i].y, &point[i].ni, &point[i].mi);
146 sum += point[i].ni;
147 }
148 //Dinic g;
149 g.ClearAll(maxn);
150 for(int i = 0; i < n; i++) {
151 int left = i + 1; int right = n + left;
152 g.AddEdge(0, left, point[i].ni);
153 g.AddEdge(left, right, point[i].mi);
154 g.AddEdge(right, left, point[i].mi);
155 for(int j = i + 1; j < n; j++) {
156 if( i == j)
157 continue;
158 if(d - get_dist(point[i], point[j]) > 0.00001) {
159 g.AddEdge(right, j + 1, INF);
160 g.AddEdge(j + 1 + n, left, INF);
161 }
162 }
163 }
164 //printf("*%d\n",sum);
165 int c = 0;
166 for(int i = 0; i < n; i++) {
167 int s = 0; int t = i + 1;
168 g.init();
169 if(g.MaxFlow(s, t, INF) == sum)
170 printf(c++ ? " %d" : "%d",i);
171 //printf("%d\n",g.MaxFlow(s, t));
172 }
173 if(c == 0)
174 printf("-1");
175 puts("");
176 }
177 return 0;
178 }
hlg1512March of the Penguins【无向图+拆点】