poj 3057 Evacuation 二分图匹配+bfs

题意:见挑战230页

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
int n,m,x,y;
vector<int> G[100005];
vector<int> dx,dy,px,py;
char field[15][15];
int xx[4]={-1,1,0,0},yy[4]={0,0,1,-1};
int sroad[15][15][15][15],dist[15][15];
int used[30000],match[1000000];
void add_edge(int u,int v)
{
    G[u].push_back(v);
    G[v].push_back(u);
}
void bfs(int x,int y)
{
    memset(dist,-1,sizeof(dist));
    dist[x][y]=0;
    queue<int> qx,qy;
    qx.push(x);
    qy.push(y);
    while(!qx.empty())
    {
      int sx=qx.front();
      int sy=qy.front();
      for(int i=0;i<=3;i++)
      {
        int tx=sx+xx[i],ty=sy+yy[i];
        if(tx>=0&&tx<n&&ty>=0&&ty<m)
            if(field[tx][ty]=='.'&&dist[tx][ty]<0)
             {
               dist[tx][ty]=dist[sx][sy]+1;
               sroad[x][y][tx][ty]=dist[tx][ty];
               qx.push(tx);
               qy.push(ty);
             }
      }
      qx.pop();
      qy.pop();
    }
}
int dfs(int u)
{
    used[u]=1;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i],w=match[v];
        if(w<0||!used[w]&&dfs(w))
        {
            match[u]=v;
            match[v]=u;
            return 1;
        }
    }
    return 0;
}
int pipei(int t)
{
    int res=0;
    for(int i=0;i<dx.size();i++)
       {
           int u=i+t*dx.size();
           if(match[u]<0)
              {
                  memset(used,0,sizeof(used));
                  if(dfs(u))
                     res++;
              }
       }
    return res;
}
int num(int t)
{
      for(int i=0;i<px.size();i++)
       for(int j=0;j<dx.size();j++)
       {
           int renx=px[i],reny=py[i];
           int menx=dx[j],meny=dy[j];
           if(sroad[menx][meny][renx][reny]<=t)
              add_edge(t*dx.size()+j,(n*m+10)*dx.size()+10+i);
       }
       return pipei(t);
}
void solve()
{
    memset(match,-1,sizeof(match));
    int ans=0;
    for(int t=0;t<=n*m+3;t++)
        {
            ans+=num(t);
            if(ans>=px.size())
            {
                cout<<t<<endl;
                return;
            }
        }
    cout<<"impossible"<<endl;
}
int main()
{
    int cas;
    cin>>cas;
    while(cas--)
    {
        scanf("%d %d",&n,&m);
        dx.clear();dy.clear();
        px.clear();py.clear();
        for(int i=0;i<=100005;i++)
            G[i].clear();
        for(int i=0;i<n;i++)
            scanf("%s",field[i]);
        memset(sroad,inf,sizeof(sroad));
        for(int i=0;i<n;i++)
          {
              for(int j=0;j<m;j++)
                if(field[i][j]=='D')
                 {
                    dx.push_back(i);
                    dy.push_back(j);
                    bfs(i,j);
                 }
                 else if(field[i][j]=='.')
                 {
                    px.push_back(i);
                    py.push_back(j);
                 }
          }
       solve();
    }
    return 0;
}

 分析:强大的二分匹配(因为一个门一时刻只能通过一个人),这是我的做法,用的是枚举时间

不过看挑战上是直接枚举时间和门组成的二元组的点,每次dfs该点,进行一次匈牙利算法,最后再算出时间

好像程序可以简化一点,不过我的这份代码的效率比较高,排名在270多名,不过开的数组大小很关键,在这个上wa了很多次。

下面是wa代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
int n,m,x,y;
vector<int> G[1005];
vector<int> dx,dy,px,py;
char field[15][15];
int xx[4]={-1,1,0,0},yy[4]={0,0,1,-1};
int sroad[15][15][15][15],dist[15][15];
int used[150],match[10000];
void add_edge(int u,int v)
{
    G[u].push_back(v);
    G[v].push_back(u);
}
void bfs(int x,int y)
{
    memset(dist,-1,sizeof(dist));
    dist[x][y]=0;
    queue<int> qx,qy;
    qx.push(x);
    qy.push(y);
    while(!qx.empty())
    {
      for(int i=0;i<=3;i++)
      {
        int tx=qx.front()+xx[i],ty=qy.front()+yy[i];
        if(tx>=0&&tx<n&&ty>=0&&ty<m)
            if(field[tx][ty]=='.'&&dist[tx][ty]<0)
             {
               dist[tx][ty]=dist[x][y]+1;
               sroad[x][y][tx][ty]=dist[tx][ty];
               qx.push(tx);
               qy.push(ty);
             }
      }
      qx.pop();
      qy.pop();
    }
}
int dfs(int u)
{
    used[u]=1;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i],w=match[v];
        //printf("%d %d\n",v,match[v]);
       // printf("match: %d  w:%d\n",match[v],w);
        if(w<0||!used[w]&&dfs(w))
        {
            match[u]=v;
            match[v]=u;
            //printf("wwwww\n");
            return 1;
        }
    }
    return 0;
}
int pipei(int t)
{
    int res=0;
    for(int i=0;i<dx.size();i++)
       {
           int u=i+t*dx.size();
          //printf("4  match:%d\n",match[0]);
           if(match[u]<0)
              {
                  memset(used,0,sizeof(used));
                  if(dfs(u))
                     res++;
              }
       }
   // printf("res:%d\n",res);
    return res;
}
int num(int t)
{
      for(int i=0;i<px.size();i++)
       for(int j=0;j<dx.size();j++)
       {
           int renx=px[i],reny=py[i];
           int menx=dx[j],meny=dy[j];
           if(sroad[menx][meny][renx][reny]<=t)
              add_edge(t*dx.size()+j,px.size()*dx.size()+10+i);
       }
       //printf("3  match:%d\n",match[0]);
       return pipei(t);
}
void solve()
{
    memset(match,-1,sizeof(match));
    //printf("1  match:%d\n",match[0]);
    int ans=0;
    for(int t=0;t<=n*m+3;t++)
        {
            ans+=num(t);
            //cout<<t<<"    "<<num(t)<<endl;
            //printf("2  match:%d\n",match[0]);
            if(ans>=px.size())
            {
                cout<<t<<endl;
                return;
            }
        }
    cout<<"impossible"<<endl;
}
int main()
{
    int cas;
    cin>>cas;
    while(cas--)
    {
        scanf("%d %d",&n,&m);
        dx.clear();dy.clear();
        px.clear();py.clear();
        for(int i=0;i<=500;i++)
            G[i].clear();
        for(int i=0;i<n;i++)
            scanf("%s",field[i]);
        memset(sroad,inf,sizeof(sroad));
        for(int i=0;i<n;i++)
          {
              for(int j=0;j<m;j++)
                if(field[i][j]=='D')
                 {
                    dx.push_back(i);
                    dy.push_back(j);
                    bfs(i,j);
                 }
                 else if(field[i][j]=='.')
                 {
                    px.push_back(i);
                    py.push_back(j);
                 }
          }
       solve();
    }
    return 0;
}

  

你可能感兴趣的:(poj 3057 Evacuation 二分图匹配+bfs)