POJ 3057 Evacuation(一道很好可以加强对二分图理解的题目)

来源:互联网 发布:win10 无网络访问权限 编辑:程序博客网 时间:2024/06/04 19:29

这是挑战上面的一道题。

一开始我按照自己思路,先跑一遍bfs,得到每个人到门的距离,然后每分钟都建立一次二分图,跑一遍二分图,用总人数减去跑出来得到的结果,直到0才停止。
但是,这样的做法是错误的。我自己拿了网上别人AC的代码然后自己造数据发现,下面这一组数据我跑出来的有问题
6 6
XDXXXX
D....D
X.X..X
X.XX.X
X...XX
XXXDXX
答案应该是4但是我的却是5,原因在于在第二秒的时候第二行第三个点被第二行最右边的D匹配掉了,后面无法更正这个结果,导致了第二行右边的D接管了靠近他的五个点。
所以正确的做法依然是,一个门在每个时间点都建立,然后左边是人,右边是门来跑二分图,这样他才会更正上面不是最优的结果。


参考了挑战上面的解法。

代码如下:

#include<iostream>#include<cstdio>#include<vector>#include<queue>#include<utility>#include<stack>#include<algorithm>#include<cstring>#include<string>using namespace std;typedef pair<int, int> pii;const int maxn = 1005;int n, m;int p_x[maxn], p_y[maxn], d_x[maxn], d_y[maxn], p, d;char graph[maxn][maxn];bool vst[15][15];int dis[15][15][15][15], dir[][2] = {0, 1, 0, -1, 1, 0, -1, 0};int uN, vN;  //u,v数目vector <int> G[maxn];int linker[4805];bool used[4805];bool dfs(int u){    for(int i = 0; i < G[u].size(); i++) {    int v = G[u][i];        if(!used[v])        {            used[v] = true;            if(linker[v] == -1 || dfs(linker[v]))            {                linker[v] = u;                return true;            }            }      }    return false;  }    int hungary(){    int res = 0;    int u;    memset(linker, -1, sizeof(linker));    for(u = 0; u < uN; u++)    {        memset(used, 0, sizeof(used));        if(dfs(u))  res++;    }     return res;   }     int solve() {uN = p;vN = 0;for(int t = 1; t < 105; t++) {vN = t * d;for(int i = 0; i < p; i++) {for(int j = 0; j < d; j++) {int tmp = dis[ p_x[i] ][ p_y[i] ][ d_x[j] ][ d_y[j] ];if(tmp != -1 && tmp <= t) {G[i].push_back((t - 1) * d + j);}}}int res = hungary();if(res == p)return t;}return -1;}struct node{int x, y, step;node(){}node(int a, int b, int c) {x = a;y = b;step = c;}};inline bool Check(int x, int y) {if(x >= 0 && x < n && y >= 0 && y < m && !vst[x][y] && graph[x][y] == '.')return 1;return 0;}inline void bfs(int sx, int sy) {node now, next;memset(vst, 0, sizeof(vst));queue <node> q;q.push(node(sx, sy, 0));vst[sx][sy] = 1;while(!q.empty()) {now = q.front();q.pop();next.step = now.step + 1;for(int i = 0; i < 4; i++) {next.x = now.x + dir[i][0];next.y = now.y + dir[i][1];if(Check(next.x, next.y)) {q.push(next);vst[next.x][next.y] = 1;dis[next.x][next.y][sx][sy] = next.step;}}}}int main() {#ifndef ONLINE_JUDGEfreopen("poj_in.txt", "r", stdin);//    freopen("poj_out.txt", "w", stdout);#endifint T;cin >> T;while(T--) {cin >> n >> m;p = d = 0;memset(dis, -1, sizeof(dis));for(int i = 0; i < maxn; i++)G[i].clear();for(int i = 0; i < n; i++) scanf("%s", &graph[i]);for(int i = 0; i < n; i++) {for(int j = 0; j < m; j++) {if(graph[i][j] == 'D') {d_x[d] = i;d_y[d++] = j;bfs(i, j);} else if(graph[i][j] == '.') {p_x[p] = i;p_y[p++] = j;}}}int ans = solve();if(ans != -1)printf("%d\n", ans);elseprintf("impossible\n");}return 0;}