洛谷 [P2825] 游戏

二分图匹配的匈牙利算法

这道题,如果没有硬石头的限制,那么就与ZJOI 2007矩阵游戏完全一样,但是如果有了硬石头的限制,我们就不能将整行整列作为元素建图,我们可以以硬石头为边界,将每一行、每一列分成若干段建图,然后跑二分图匹配即可。

这里我们总结一下类似问题的特征:

  1. 最优性问题或判定性问题
  2. 需要求出行和列的一一对应关系
#include 
#include 
#include 
#include 
using namespace std;
int init(){
    int rv=0,fh=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') fh=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        rv=(rv<<1)+(rv<<3)+c-'0';
        c=getchar();
    }
    return rv*fh;
}
int m,n,tot=1,tag1[55][55],tag2[55][55],g[2505][1000],match[10505];
char dt[55][55];
bool f[2505];
bool hungarian(int u){
    for(int i=1;i<=g[u][0];i++){
        int v=g[u][i];
        if(!f[v]){
            f[v]=1;
            if(!match[v]||hungarian(match[v])){
                match[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    n=init();m=init();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf(" %c ",&dt[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        int j=1;
        while(j<=m){
            if(dt[i][j]=='#') {if(j!=1)  tot++;}
            else tag1[i][j]=tot;
            j++;
        }
        tot++;
    }
    int ma=tot-1;
    for(int j=1;j<=m;j++){
        int i=1;
        while(i<=n){
            if(dt[i][j]=='#') {if(i!=-1) tot++;}
            else tag2[i][j]=tot;
            i++;
        }
        tot++;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(dt[i][j]=='*'){
                int a=tag1[i][j],b=tag2[i][j];
                g[a][++g[a][0]]=b;
            }
        }
    }
    int ans=0;
    for(int i=1;i<=ma;i++){
        memset(f,0,sizeof(f));
        if(hungarian(i)) ans++;
    }
    cout<

转载于:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8270655.html

你可能感兴趣的:(洛谷 [P2825] 游戏)