Sgu 438 The Glorious Karlutka River(動態流)

題目地址: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 debug
using 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 debu
	freopen("in.txt", "r", stdin);
#endif // debug

	int 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;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章