Sgu 438 The Glorious Karlutka River(动态流)

来源:互联网 发布:短篇小说推荐 知乎 编辑:程序博客网 时间:2024/05/21 06:01

题目地址:http://acm.sgu.ru/problem.php?contest=0&problem=438

思路:

1.由于不同时刻,两点的流量不同,故不能在一张图中求解。

2.由于任意时刻,人可在中间节点停留,故费用流无法解决此题。

3.给定所有流量限制,求最短经过时间。可通过枚举时间,将中间节点按时间拆点为(i,t)(即在时间t时的点i)。

(1)节点存在容量限制,可通过拆点解决:对于点i,连边(i,t)->(i',t),容量为c[i],仍处于该点时间不变。

(2)若能从i点一次跳到j点,则连边(i',t)->(j,t+1),容量为INF,代表在时间t当前处于i的点,下一秒可到达j点。

(3)对于所有能从岸边一次到达的点,连边S->(i,t);对于能一次到达岸边的点,连边(i',t)->T。

(4)每次在原图的基础上添加点与边,每次在残量网络中求最大流,也即为时间t时通过人数,累加直到总人数大于等于m时的时间即为最小时间。

4.最大时间为n+m:每个点只能留一人,每个人经过每个点的时间。

#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const int maxn = 25000 + 50;const int maxm = 5000 + 50;const int INF = 0x3f3f3f3f;struct edge{int to, nt;};struct Node{int x, y, c;};struct Edge{int from, to, cap, flow;Edge(int a, int b, int c, int d) :from(a), to(b), cap(c), flow(d) {}};struct Dinic{int n, m, s, t;vector<Edge> edges;vector<int> G[maxn];bool vis[maxn];int d[maxn];int cur[maxn];void init(int n){this->n = n;for (int i = 0; i <= n; i++) G[i].clear();edges.clear();}void addEdge(int from, int to, int cap){edges.push_back(Edge(from, to, cap, 0));edges.push_back(Edge(to, from, 0, 0));m = edges.size();G[from].push_back(m - 2);G[to].push_back(m - 1);}bool BFS(){memset(vis, 0, sizeof(vis));queue<int> Q;Q.push(s);vis[s] = 1;d[s] = 0;while (!Q.empty()){int x = Q.front();Q.pop();for (int i = 0; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if (!vis[e.to] && e.cap > e.flow){vis[e.to] = 1;d[e.to] = d[x] + 1;Q.push(e.to);}}}return vis[t];}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++){Edge& e = edges[G[x][i]];if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){e.flow += f;edges[G[x][i] ^ 1].flow -= f;flow += f;a -= f;if (a == 0) break;}}return flow;}int MaxFlow(int s, int t){this->s = s;this->t = t;int flow = 0;while (BFS()){memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}return flow;}};Dinic g;Node a[55];int head[55];edge edges[maxm];int n, m, d, w, tot, S, T;void addEdge(int u, int v){edges[tot].to = v, edges[tot].nt = head[u], head[u] = tot++;}double dist(Node a, Node b){return sqrt(1.0*(a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));}int main(){#ifdef debufreopen("in.txt", "r", stdin);#endif // debugint f1 = 0, f2 = 0;memset(head, -1, sizeof(head));scanf("%d%d%d%d", &n, &m, &d, &w);S = 0, T = 401 * n + 2;for (int i = 1; i <= n; i++){scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].c);if (a[i].y <= d){f1 = 1, addEdge(0, i);}if (a[i].y + d >= w){f2 = 1, addEdge(n + 1, i);}}if (w <= d) printf("1\n");else{for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if ((i != j) && dist(a[i], a[j]) <= d){addEdge(i, j);}}}int ans = -1, tot = 0;if (f1&&f2){for (int t = 1; t <= n + m; t++){for (int i = head[0]; ~i; i = edges[i].nt){int nt = edges[i].to;g.addEdge(S, (t - 1)*n + 1 + nt, INF);}for (int i = head[n + 1]; ~i; i = edges[i].nt){int nt = edges[i].to;g.addEdge((200 + t)*n + 1 + nt, T, INF);}for (int i = 1; i <= n; i++){g.addEdge((t - 1)*n + 1 + i, (200 + t)*n + 1 + i, a[i].c);for (int j = head[i]; ~j; j = edges[j].nt){int nt = edges[j].to;g.addEdge((200 + t)*n + 1 + i, t*n + 1 + nt,INF);}}tot += g.MaxFlow(S, T);if (tot >= m){ans = t + 1;break;}}}if (ans == -1) printf("IMPOSSIBLE\n");else printf("%d\n", ans);}return 0;}




阅读全文
0 0
原创粉丝点击