POJ 3057 Evacuation 二分图匹配

每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间。

不断增加时间,然后增广,直到最大匹配。


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<cmath>
#include<climits>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define pb(a) push(a)
#define INF 0x1f1f1f1f
#define lson idx<<1,l,mid

#define rson idx<<1|1,mid+1,r
#define PI 3.1415926535898
template<class T> T min(const T& a,const T& b,const T& c)
{
return min(min(a,b),min(a,c));
}
template<class T> T max(const T& a,const T& b,const T& c)
{
return max(max(a,b),max(a,c));
}
void debug()
{
#ifdef ONLINE_JUDGE
#else
freopen("data.in","r",stdin);
// freopen("d:\\out1.txt","w",stdout);
#endif
}
int getch()
{
int ch;
while((ch=getchar())!=EOF)
{
if(ch!=‘ ‘&&ch!=‘\n‘)return ch;
}
return EOF;
}

int DX[] = {0, 1, 0, -1};
int DY[] = {1, 0, -1, 0};

const int maxn = 15;
char grid[maxn][maxn];
int n, m;
int dist[maxn][maxn][maxn][maxn];
int vis[maxn][maxn];
vector<int> dx,dy,px,py;

void bfs(int X,int Y)
{
queue<int> qx,qy;
qx.push(X); qy.push(Y);
memset(vis, 0, sizeof(vis));
vis[X][Y] = true;
while(!qx.empty())
{
int x = qx.front(); qx.pop();
int y = qy.front(); qy.pop();
for(int d=0; d<4; d++)
{
int nx = x + DX[d];
int ny = y + DY[d];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&grid[nx][ny]==‘.‘&&!vis[nx][ny])
{
vis[nx][ny] = true;
dist[X][Y][nx][ny] = dist[X][Y][x][y] + 1;
qx.push(nx);
qy.push(ny);
}
}
}
}

void prework()
{
memset(dist, -1, sizeof(dist));
dx.clear(); dy.clear();
px.clear(); py.clear();

for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
if(grid[i][j]==‘D‘)
{
dx.push_back(i);
dy.push_back(j);
dist[i][j][i][j]=0;
bfs(i, j);
}else if(grid[i][j]==‘.‘)
{
px.push_back(i);
py.push_back(j);
}
}
//printf("prework: %d %d\n",dx.size(), px.size());
}

const int maxv = 101*50 + 110;
int id[maxn][maxn][110];
bool used[maxv];
int match[maxv];
int vcnt;
vector<int> g[maxv];
int ID(int x, int y, int t)
{
int &a = id[x][y][t];
if(a==0) a=++vcnt;
return a;
}
void add(int u,int v)
{
g[u].push_back(v);
g[v].push_back(u);
}
void init()
{
for(int i=1; i<maxv; i++)
g[i].clear();
memset(id, 0, sizeof(id));
}
bool dfs(int u)
{
used[u] = true;
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
int w = match[v];
if(w<0||!used[w]&&dfs(w))
{
match[u] = v;
match[v] = u;
return true;
}
}
return false;
}
int solve()
{
init();
memset(match, -1, sizeof(match));
int res = 0;
vcnt = 0;
if(px.size() == 0) return 0;
for(int t=1; t<=100; t++)
{
for(int i=0; i<dx.size(); i++)
{
for(int j=0; j<px.size(); j++)
{
int dis = dist[dx[i]][dy[i]][px[j]][py[j]];
if(dis!=-1 && dis <= t)
{
int u = ID(dx[i], dy[i], t);
int v = ID(px[j], py[j], 0);
add(u, v);
add(v, u);
}
}
}
for(int i=0; i<dx.size(); i++)
{
int u = ID(dx[i], dy[i], t);
memset(used, 0, sizeof(used));
if(dfs(u))
res++;
}
if(res == px.size()) return t;
}
return -1;
}
int main()
{
debug();
int t;
scanf("%d", &t);
for(int ca=1; ca<=t; ca++)
{
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
scanf("%s", grid[i]+1);

prework();

int ans = solve();
if(ans != -1)
printf("%d\n", ans);
else printf("impossible\n");
}
return 0;
}

POJ 3057 Evacuation 二分图匹配

时间: 2024-08-10 06:17:06

POJ 3057 Evacuation 二分图匹配的相关文章

poj 3692 Kindergarten(二分图匹配)

题意:n个男孩相互认识,m个女孩相互认识,k对男孩和女孩相互认识,求最大的任意两人相互认识的集合: 思路:二分图匹配: 独立集=总数-最大匹配数: 最大团=原图补图的最大独立集=总数-补图的最大匹配数: 本题就是求最大团,先求补图的最大匹配数,匈牙利算法: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,m; int mm[505][505]; int

POJ 3020-Antenna Placement(二分图匹配_最小路径覆盖+前向星构图)

Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6930   Accepted: 3439 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most st

POJ 3057 Evacuation

分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d)和p连边,按t从小到大 枚举点增广就好了.无解的情况只有一种,某个人无论如何都无法出去. /********************************************************* * --Sakura hirahira mai orite ochite-- * * au

Poj(1274),二分图匹配

题目链接:http://poj.org/problem?id=1274 The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 23088   Accepted: 10285 Description Farmer John completed his new barn just last week, complete with all the latest milking technology.

poj 2446 Chessboard (二分图利用奇偶性匹配)

Chessboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13176   Accepted: 4118 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2

POJ - 1904 King&#39;s Quest(强连通分量+二分图匹配)

题目大意:有N个帅哥和N个美女,现在给出每个帅哥所喜欢的美女的编号,和一个帅哥和美女的完美匹配 问每个帅哥可以娶多少个美女,且当他娶完这个美女后,剩下的人还可以完美匹配 解题思路:神题啊,给一个大神的详细解答 具体是这样的,首先先建边,把帅哥和能娶到的美女连边,再把完美匹配的美女和帅哥连边,这样就形成了一张有向图了 接着,找出这张有向图的所有强连通分量,在强连通分量里面的帅哥都可以娶到自己喜欢的美女,且娶完这个美女后,不会影响到其他人 为什么呢? 假设xi为帅哥,yi和yj为美女,假设给定的完美

二分图匹配 最大匹配数+最大点覆盖 POJ 1469+POJ 3041

最大匹配数就等于最大点覆盖,因为在图里面,凡是要覆盖的点必定是连通的,而最大匹配之后,若还有点没有覆盖到,则必定有新的匹配,与最大匹配数矛盾,如果去掉一些匹配,则必定有点没有覆盖到. POJ 1469 比较简单,用的经典的二分图匹配算法. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

POJ 2446 二分图匹配

题意:给你一个n*m方格 让你用1*2的的小方格去铺满,其中有k个方格不能被铺到. 思路:二分图建图, 以每个格子为点建图,如果可以用一块1*2的小方格铺到,就连一条边. 每个格子在X集合和Y集合都有一个点,只要任意一边被匹配到了就算可以,然后就是二分图匹配了. 上代码. #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector

M - Jamie&#39;s Contact Groups - poj 2289(二分图多重匹配)

题意:某个人通讯录有很多人,现在他想把这个人分组,给的数据是可以把这个人分在那些组里面,现在他想知道分组后,人最多的那个组至少有多少人. 分析:因为没有给组限制有多少人,可以使用二分求出来最小的那个,感觉还是挺暴力的.....不过时间确实很少 500多ms ******************************************************************** #include<stdio.h>#include<string.h>#include&l