题目:题目链接
March of the Penguins
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 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:
Output Per testcase:
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 |
题意:
有一群企鹅分布在一些浮冰(容量无限大)上。问你这些企鹅能不能到同一块浮冰上,如果能,输出能够。
题目有如下限制:
n块浮冰,给出每块浮冰的位置,每块浮冰上有一定数额的企鹅,且两块浮冰能通过的条件是他们的距离不大于d。
并且每块浮冰能接受离开该浮冰的企鹅数有限制。
题解:
这是一道最大流的题目。
题目的限制条件在于离开浮冰企鹅数有限制,我们可以理解为把该浮冰作为中转的企鹅数限制。由于浮冰是一个点,所以我们进行拆点,把限制条件放在了边上(i,i+n)。
然后我们进行枚举终点,来判断是不是满流。
建图的技巧在于我们设置一个超级源,与拆点之后的i连接,容量定为mi。至于终点的话,加入我们枚举的聚集在一起的浮冰为x,我们则设x为终点,并不是设x+n为终点。
每枚举完一个点,注意要把图中的流清零。
代码:
Source Code #include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL __int64 const int MOD = 1e9 + 7; const int N = 2e2 + 15; const int INF = (1 << 30) - 1; const int letter = 130; using namespace std; int n; double d1; LL x[N], y[N], n1[N], m[N]; struct node { int from, to, cap, flow; }; vector<node>edges; vector<int>G[N]; int d[N], cur[N]; int s, t; void init() { edges.clear(); for(int i = 0; i < N; i++) G[i].clear(); } void addedge(int from, int to, int cap) { edges.push_back((node) { from, to, cap, 0 }); edges.push_back((node) { to, from, 0, 0 }); int vs = edges.size(); G[from].push_back(vs - 2); G[to].push_back(vs - 1); } bool bfs(int s, int t) { memset(d, -1, sizeof(d)); queue<int>q; while(!q.empty()) q.pop(); q.push(s); d[s] = 0; while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 0; i < G[x].size(); i++) { node &e = edges[G[x][i]]; if(d[e.to] < 0 && e.cap > e.flow) { d[e.to] = d[x] + 1; if(e.to == t) return true; q.push(e.to); } } } return false; } int dfs(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i < G[x].size(); i++) { node &e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && ( f = dfs(e.to, min(a, e.cap - e.flow))) > 0) { flow += f; a -= f; edges[G[x][i]].flow += f; edges[G[x][i] ^ 1].flow -= f; if(a == 0) break; } } return flow; } int maxflow(int s, int t) { int flow = 0; while(bfs(s, t)) { memset(cur, 0, sizeof(cur)); flow += dfs(s, INF); } return flow; } bool ok(int x1, int y1, int x2, int y2, double d) { if(sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) <= d) return true; return false; } int main() { int tc; scanf("%d", &tc); while(tc--) { scanf("%d%lf", &n, &d1); s = 0; init(); LL sum = 0; for(int i = 1; i <= n; i++) { scanf("%I64d%I64d%I64d%I64d", x + i, y + i, n1 + i, m + i); sum += n1[i]; } ///jiantu for(int i = 1; i <= n; i++) addedge(i, i + n, m[i]); ///chai for(int i = 1; i <= n; i++) addedge(s, i, n1[i]); for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++) { if(ok(x[i], y[i], x[j], y[j], d1)) ///nbn { addedge(i + n, j, INF); addedge(j + n, i, INF); } } ///meiju int flag = 0;///geshi for(int i = 1; i <= n; i++) { t = i; int ans = maxflow(s, t); if(ans == sum) { if(flag) printf(" %d", i - 1); else printf("%d", i - 1); flag = 1; } for(int i = 0; i < edges.size(); i++) edges[i].flow = 0; } if(flag) printf("\n"); else puts("-1"); } return 0; }