POJ-3020-Antenna Placement [二分匹配][最小路徑覆蓋]


題目傳送門


題意:一個地圖由o*組成,一個信號塔可以覆蓋兩個連續的*。問至少需要多少個信號塔才能覆蓋所有的*

思路:先將所有的’*’hash,然後建立二分圖,用匈牙利算法算出最大匹配數。最小路徑覆蓋數 = 頂點數 - 最大匹配數

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

using namespace std;

bool path[410][410], used[410];
int match[410];
int num;
bool Dfs(int x)
{
    for (int i = 1; i <= num; i++)
    {
        if (!used[i] && path[x][i])
        {
            used[i] = true;
            if (!match[i] || Dfs(match[i]))
            {
                match[i] = x;
                return true;
            }
        }
    }
    return false;
}
int Matching()
{
    int ans = 0;
    memset(match, 0, sizeof(match));
    for (int i = 1; i <= num; i++)
    {
        memset(used, false, sizeof(used));
        if (Dfs(i))
        {
            ans++;
        }
    }
    return ans;
}
int main(void)
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n,m;
        int a[50][20];
        char mp[50][20];
        memset(a,0,sizeof(a));
        memset(path,false,sizeof(path));
        memset(mp, 0, sizeof(mp));
        num = 1;
        scanf("%d %d", &n, &m);
        for (int i = 0; i < n; i++)
            scanf(" %s", mp[i]);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (mp[i][j]=='*')
                    a[i][j] = num++;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (a[i][j])
                {
                    if (i-1>=0 && a[i-1][j])
                        path[a[i][j]][a[i-1][j]] = true;
                    if (i+1<n && a[i+1][j])
                        path[a[i][j]][a[i+1][j]] = true;
                    if (j-1>=0 && a[i][j-1])
                        path[a[i][j]][a[i][j-1]] = true;
                    if (j+1<m && a[i][j+1])
                        path[a[i][j]][a[i][j+1]] = true;
                }
            }
        }
        num--;
        int ans = Matching();
        printf("%d\n", num-ans/2);
    }
    return 0;
}
發佈了101 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章