hdu1045 Fire Net (bipartite graph matching)

analysis:

A weaker version of this title: ch6802 car placement

The difference between the two questions that ch6802 just can not put the ban point, but the car can still go through, so his party can only put a maximum of one
and hdu1045, this question is, where is prohibited wall between two cars can
easily think of the existence of the wall, his party could put two or even more cars

If there is no wall, each row share a node that is the number of rows tag,
part of the wall spaced from the wall, then the long sides of the respective marks on the line.
Similarly column

ps: After finish this problem seemed to understand a little

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=20;
char s[maxm][maxm];
int h[maxm][maxm];//标记行
int l[maxm][maxm];//标记列
vector<int>g[maxm];//存图
int n;
int nn;//行节点总数
int mark[maxm];
int now[maxm];
int dfs(int u){
    for(int i=0;i<(int)g[u].size();i++){
        int v=g[u][i];
        if(!mark[v]){
            mark[v]=1;
            if(now[v]==0||dfs(now[v])){
                now[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    while(cin>>n&&n){
        getchar();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                s[i][j]=getchar();
            }
            getchar();
        }
        int cnt=1;
        memset(h,0,sizeof h);
        memset(l,0,sizeof l);
        for(int i=1;i<=n;i++){//行标记
            for(int j=1;j<=n;j++){
                if(s[i][j]=='.'&&h[i][j]==0){
                    for(int k=j;k<=n;k++){//同一块的标记相同数字
                        if(s[i][k]=='X'){
                            break;
                        }
                        h[i][k]=cnt;
                    }
                    cnt++;
                }
            }
        }
        nn=cnt-1;//记录行标记总数量
        cnt=1;
        for(int i=1;i<=n;i++){//列标记
            for(int j=1;j<=n;j++){
                if(s[j][i]=='.'&&l[j][i]==0){
                    for(int k=j;k<=n;k++){//同一块的标记相同数字
                        if(s[k][i]=='X'){
                            break;
                        }
                        l[k][i]=cnt;
                    }
                    cnt++;
                }
            }
        }
        for(int i=1;i<=nn;i++){//清空,注意要清空到nn而不是n
            g[i].clear();
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(s[i][j]=='.'){
                    g[h[i][j]].push_back(l[i][j]);
                }
            }
        }
        memset(now,0,sizeof now);
        int ans=0;
        for(int i=1;i<=nn;i++){//直接匈牙利
            memset(mark,0,sizeof mark);
            ans+=dfs(i);
        }
        cout<<ans<<endl;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44178736/article/details/92581199