POJ 3057 二分图最大匹配

来源:互联网 发布:人工智能应用案例 编辑:程序博客网 时间:2024/06/04 08:33

比较难想的一道二分图。

考虑这么建图。

时间和门的二元组为二分图的x集合的元素,每个人为y集合的元素,连边就表示,这段时间内此门能让此人过。

让时间从1开始递增,每次寻找x集合和y集合的最大匹配,当最大匹配等于人数时,此时间满足所有人都离开屋子。

每次找最大匹配可以在上一个时间的残余图上寻找增广路,速度还是挺快的。



#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#include<vector>#include<cstdlib>using namespace std;#define MAX_V 5000#define INF 0x3f3f3f3ftypedef pair<int,int> P;bool vis[MAX_V];int match[MAX_V];bool G[MAX_V][MAX_V];int x_cnt,y_cnt;bool find_path(int u){    for(int i=0;i<y_cnt;i++)    {        if(!vis[i]&&G[u][i])        {            vis[i]=1;            if(match[i]==-1||find_path(match[i]))            {                match[i]=u;                return true;            }        }    }    return false;}int N,M;char MAP[20][20];int DIS[20][20][20][20];int dx[4]={1,0,-1,0};int dy[4]={0,1,0,-1};vector<P> DOOR;vector<P> MAN;void bfs(int u,int v,int d[20][20]){    queue<P> Q;    d[u][v]=0;    Q.push(P(u,v));    while(!Q.empty())    {        P now=Q.front(); Q.pop();        for(int i=0;i<4;i++)        {            int tx=now.first+dx[i],ty=now.second+dy[i];            if(tx>=0&&tx<N&&ty>=0&&ty<M&&MAP[tx][ty]=='.'&&d[tx][ty]==-1)            {                d[tx][ty]=d[now.first][now.second]+1;                Q.push(P(tx,ty));            }        }    }}int slove(){    memset(G,0,sizeof(G));    memset(match,-1,sizeof(match));    x_cnt=DOOR.size();    y_cnt=MAN.size();    int res=0;    for(int T=0;T<N*M;T++)    {        for(int i=0;i<DOOR.size();i++)        {            for(int j=0;j<MAN.size();j++)            {                int doorx=DOOR[i].first,doory=DOOR[i].second;                int manx=MAN[j].first,many=MAN[j].second;                if(DIS[doorx][doory][manx][many]!=-1&&DIS[doorx][doory][manx][many]<=T+1&&G[i][j]==0) {  G[i][j]=1; }            }        }        for(int i=0;i<x_cnt;i++)        {            memset(vis,0,sizeof(vis));            if(find_path(i)) res++;        }        if(res==MAN.size()) return T+1;    }    return -1;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        DOOR.clear();        MAN.clear();        scanf("%d%d",&N,&M);        for(int i=0;i<N;i++)        {            scanf("%s",MAP[i]);        }        memset(DIS,-1,sizeof(DIS));        for(int i=0;i<N;i++)        {            for(int j=0;j<M;j++)            {                if(MAP[i][j]=='D')                {                    DOOR.push_back(P(i,j));                    bfs(i,j,DIS[i][j]);                }                else if(MAP[i][j]=='.') MAN.push_back(P(i,j));            }        }        int ans=slove();        if(ans==-1) printf("impossible\n");        else printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击