lightoj1150 - Ghosts!

先预处理出来每个ghost到每个human后杀掉他后返回窝的最少时间。

然后人份时间上限建图,二分匹配判断匹配数目是否等于human的数目。。。

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2015
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 30;

int dx[] = {-1,0,1,0};
int dy[] = {0,-1,0,1};

vector<ii> G[N*N];

char g[N][N];
int n;
int A[N][N], B[N][N];
int uN, vN;
void input() {
	scanf("%d",&n);
	uN = vN = 0;
	memset(A, 0,sizeof A);
	memset(B, 0,sizeof B);
	for (int i = 1;i <= n;++i) {
		scanf("%s", g[i] + 1);
		for (int j = 1;j <= n;++j) {
			if (g[i][j] == 'G') {
				A[i][j] = ++uN;
			}
			if (g[i][j] == 'H') {
				B[i][j] = ++vN;
			}
		}
	}
}
bool vis[N][N];
int dis[N][N];
bool check(int x,int y) {
	if (vis[x][y]) return false;
	if (x < 1 || x > n || y < 1 || y > n || g[x][y] == '#') return false;
	return true;
}
void bfs(int x,int y) {
	memset(vis, false,sizeof vis);
	memset(dis, -1,sizeof dis);
	dis[x][y] = 0;
	vis[x][y] = true;
	queue<ii> que;
	que.push(ii(x, y));
	while(!que.empty()) {
		ii tmp = que.front();
		que.pop();
		for (int i = 0;i < 4;++i) {
			int nx = tmp.first + dx[i];
			int ny = tmp.second + dy[i];
			if (check(nx,ny)) {
				dis[nx][ny] = dis[tmp.first][tmp.second] + 1;
				que.push(ii(nx,ny));
				vis[nx][ny] = true;
				if (g[nx][ny] == 'H') {
					G[A[x][y]].push_back(ii(B[nx][ny], dis[nx][ny] * 2 + 2));
				}
			}
		}
	}
}
void Initation() {
	for (int i = 1;i <= uN;++i)
		G[i].clear();
	for (int i = 1;i <= n;++i) {
		for (int j = 1;j <= n;++j) {
			if (g[i][j] == 'G') bfs(i, j);
		}
	}
}

vector<int> mp[N*N];
void getmap(int x) {
	for (int i = 1;i <= uN;++i) {
		mp[i].clear();
		for (int j = 0;j < G[i].size();++j) {
			if (G[i][j].second <= x) mp[i].push_back(G[i][j].first);
		}
	}
}
int linker[N*N];
bool mark[N*N];
bool search(int u) {
	for (int i = 0;i < mp[u].size();++i) {
		int v = mp[u][i];
		if (mark[v]) continue;
		mark[v] = true;
		if (linker[v] == -1 || search(linker[v])) {
			linker[v] = u;
			return true;
		}
	}
	return false;
}
int hungary() {
	int ans = 0;
	memset(linker, -1,sizeof linker);
	for (int i = 1;i <= uN;++i) {
		memset(mark, false,sizeof mark);
		if (search(i)) ans++;
	}
	return ans;
}
int binary() {
	int ans = -1;
	int low = 1, high = 100000;
	while(low <= high) {
		int mid = (low + high) / 2;
		getmap(mid);
		int tmp = hungary();
		if (tmp == vN) {
			ans = mid;
			high = mid - 1;
		}else low = mid + 1;
	}
	return ans;
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out1.txt","w",stdout);
	int t, icase = 0;
	scanf("%d",&t);
	while(t--) {
		input();
		Initation();
		int ans = binary();
		printf("Case %d: ", ++icase);
		if (ans == -1)  puts("Vuter Dol Kupokat");
		else printf("%d\n", ans);
	}
	return 0;
}


你可能感兴趣的:(二分,lightoj)