poj 3057 Evacuation (二分图匹配)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40993793/article/details/82188056

传送门:http://poj.org/problem?id=3057

题意:

  有X*Y个点,每个点可能是'X'(墙壁),'.'(人),'D'(门),周围一圈只可能是'X','D'。每个门在同一时刻只能出去一个人,每个人每个时刻只能走一格,问全部人撤离最少需要多少时间。

思路:

  首先bfs预处理每个门到每个人的最短距离,如果有人无法到达所有门,那么直接输出"impossible"。

  之后将每个人作为一个点。将每个时刻的每个门作为一个点,若该时刻这扇门与这个人的距离小于等于时刻,则两者连边。利用二分图匹配,当匹配数等于人数的时候,该时刻就是答案。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs id*2+1
#define Mod(a,b) a<b?a:a%b+b 
using namespace std;

const int maxn = 100010;
const ll M = 1e9 + 7;
const ll INF = 1e9;
const int N = 10000;
const double e = 10e-6;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };

int V;
vector<int> G[N];
int match[N];
bool used[N];
void addEdge(int u, int v)
{
	G[u].push_back(v); G[v].push_back(u);
}
void init()
{
	for (int i = 0; i < N; i++)
		G[i].clear();
}
bool dfs(int v)
{
	used[v] = true;
	for (int i = 0; i < G[v].size(); i++) {
		int u = G[v][i], w = match[u];
		if (w < 0 || !used[w] && dfs(w)) {
			match[v] = u; match[u] = v;
			return true;
		}
	}
	return false;
}

int n, m;
char maze[20][20];
vector<P> d, p;
int id[20][20];
int dis[200][200];

struct node
{
	P p;
	int dis;
};

void bfs(int u)
{
	queue<node> que; que.push(node{ d[u], 0 });
	while (!que.empty()) {
		node v = que.front(); que.pop();
		for (int i = 0; i < 4; i++) {
			int x = v.p.first + dx[i], y = v.p.second + dy[i];
			if (x < 0 || x >= n || y < 0 || y >= m)continue;			
			if (maze[x][y] == '.'&&dis[u][id[x][y]] == -1) {
				que.push(node{ P(x,y),v.dis + 1 });
				dis[u][id[x][y]] = v.dis + 1;
			}
		}
	}
}

int main() {
	int t;
	scanf("%d", &t); getchar();
	while (t--) {
		init(); d.clear(); p.clear();
		memset(dis, -1, sizeof(dis));
		memset(id, 0, sizeof(id));
		scanf("%d%d", &n, &m); getchar();

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				maze[i][j] = getchar();
				if (maze[i][j] == 'D')
					d.push_back(P(i, j));
				else if (maze[i][j] == '.') {
					id[i][j] = p.size();
					p.push_back(P(i, j));
				}
			}
			getchar();
		}

		for (int i = 0; i < d.size(); i++)
			bfs(i);
		bool judge = false;
		for (int i = 0; i < p.size(); i++) {
			judge = true;
			for (int j = 0; j < d.size(); j++) {
				if (dis[j][i] >= 0) {
					judge = false;
					break;
				}
			}
			if (judge)
				break;
		}
		if (judge) {
			puts("impossible");
			continue;
		}

		int cnt = 0, ans = 0;
		memset(match, -1, sizeof(match));
		int now = p.size();

		while (cnt < p.size()) {
			ans++;
			for (int i = 0; i < d.size(); i++) {
				for (int j = 0; j < p.size(); j++) {
					if (0 <= dis[i][j] && dis[i][j] <= ans)
						addEdge(now, j);
				}
				memset(used, 0, sizeof(used));
				if (dfs(now))
					cnt++;
				now++;
			}
		}
		printf("%d\n", ans);
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40993793/article/details/82188056