HDU5093 Battle ships (BZOJ4554)

来源:互联网 发布:djvu mac 打开 编辑:程序博客网 时间:2024/06/01 10:19

二分图最大匹配

题目传送门HDU

题目传送门BZOJ

因为两个差不多,这里只写HDU的。交BZOJ的话把t给删了就行。

题目大意:给你n*m的一个图,其中‘*’表示正常海面,‘#’表示冰山,‘o’表示浮冰。你要放尽可能多的船。船不能放在浮冰或冰山上。同一行同一列只能放一条船,除非中间有冰山隔着。输出最多能放的船的数量。

思路:先只考虑行的情况,把每只战船影响的范围称为一个”块“。给每一个块编号,把结果保存在一个二维数组中。x[i][j]存坐标为i,j的编号。列的话同样做,存在另一个数组中。
我们可以把行看成A集合,把列看成B集合。然后就可以愉快的连边啦。连完边后最多能放的船的数量就相当于跑一个最大匹配就可以啦。

贴上代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct edge{    int next;    int to;};edge a[2505];int t,n,m,k,nx,sum;int x[55][55],y[55][55];int h[1255],who[1255];char c[55][55];bool f[1255];void build_x(int i){    bool flag=true;    for (int j=0;j<m;j++){        if (c[i][j]=='*'){            if (flag) { sum++; flag=false; }            x[i][j]=sum;        }        if (c[i][j]=='#')            flag=true;    }}void build_y(int i){    bool flag=true;    for (int j=0;j<n;j++){        if (c[j][i]=='*'){            if (flag) { sum++; flag=false; }            y[j][i]=sum;        }        if (c[j][i]=='#')            flag=true;    }}void read(int u,int v){    k++;    a[k].next=h[u];    a[k].to=v;    h[u]=k;}bool dfs(int i){    if (f[i])        return false;    f[i]=true;    for (int j=h[i];j;j=a[j].next){        if (!who[a[j].to]||dfs(who[a[j].to])){            who[a[j].to]=i;            return true;        }    }    return false;}int main(){    scanf("%d",&t);    while (t--){        memset(x,0,sizeof(x));        memset(y,0,sizeof(y));        memset(h,0,sizeof(h));        memset(who,0,sizeof(who));        k=0;        scanf("%d%d",&n,&m);        for (int i=0;i<n;i++)            scanf("%s",c[i]);        sum=0;        for (int i=0;i<n;i++)            build_x(i);        nx=sum;        sum=0;        for (int i=0;i<m;i++)            build_y(i);        for (int i=0;i<n;i++)            for (int j=0;j<m;j++)                if (x[i][j]!=0&&y[i][j]!=0)                    read(x[i][j],y[i][j]);        int ans=0;        for (int i=1;i<=nx;i++){            memset(f,false,sizeof(f));            if (dfs(i))                ans++;        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击