poj 3020 二分圖最小路徑覆蓋

二分圖最小路徑覆蓋=|v|-最大匹配。此題爲有向圖,切所有邊正反向存了兩遍,所以結果匹配數要除以2

//
//  main.cpp
//  poj3020
//
//  Created by Fangpin on 15/5/29.
//  Copyright (c) 2015年 FangPin. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace  std;
const int MAXN=5000;
int link[MAXN],n,m,total,h[50][20];
vector<int> g[MAXN];
char mp[55][22];
bool vis[MAXN];

bool dfs(int x){
    for(int i=0;i<g[x].size();++i){
        int y=g[x][i];
        if(vis[y]) continue;
        vis[y]=true;
        if(link[y]==-1 || dfs(link[y])){
            link[y]=x;
            return true;
        }
    }
    return false;
}

int hungry(){
    memset(link,-1,sizeof(link));
    int ans=0;
    for(int i=1;i<=total;++i){
        memset(vis,false,sizeof(vis));
        if(dfs(i)) ++ans;
    }
    return ans;
}

int main(int argc, const char * argv[]) {
    // insert code here...
//    std::cout << "Hello, World!\n";
    int t;
    scanf("%d",&t);
    char s[10000];
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n*m;++i) g[i].clear();
        memset(mp,'o',sizeof(mp));
        total=0;
        for(int i=0;i<n;++i){
            scanf("%s",s);
            int len=strlen(s);
            for(int j=0;j<len;++j){
                mp[i+1][j+1]=s[j];
                if(s[j]=='*') h[i+1][j+1]=++total;
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                if(mp[i][j]=='*'){
                    int x=h[i][j];
                    if(mp[i-1][j]=='*') g[x].push_back(h[i-1][j]);
                    if(mp[i+1][j]=='*') g[x].push_back(h[i+1][j]);
                    if(mp[i][j-1]=='*') g[x].push_back(h[i][j-1]);
                    if(mp[i][j+1]=='*') g[x].push_back(h[i][j+1]);
                }
            }
        }
        cout<<total-hungry()/2<<endl;
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章