• POJ


    http://poj.org/problem?id=3020

    首先注意到,答案的最大值是'*'的个数,也就是相当于我每用一次那个技能,我只套一个'*',是等价的。

    所以,每结合一对**,则可以减少一次使用,所以就是找**的最大匹配数目。

    对于每一个*,和它的上下左右连接一条边(如果是*才连)

    那么,这个图是一个二分图,怎么找到左边集合S,右边集合T呢?

    我的做法是染色一次,就可以。

    这题应该不能贪心吧。

    3 5

    *****

    o***o

    o*o*o

    其实也可以不分开S、T

    跑一发最大匹配,然后匹配数 / 2即可。意思就是match[1] = 2,也可以match[2] = 1,但是两者是只算一个匹配。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 40 + 20;
    char str[maxn][maxn];
    int a[maxn][maxn];
    struct Node {
        int u, v, tonext;
    }e[maxn * maxn * 3];
    int first[maxn * maxn * 3], num;
    void addEdge(int u, int v) {
        ++num;
        e[num].u = u, e[num].v = v;
        e[num].tonext = first[u];
        first[u] = num;
    }
    int match[maxn * maxn * 3], book[maxn * maxn * 3], DFN;
    bool dfs(int u) {
        for (int i = first[u]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (book[v] == DFN) continue;
            book[v] = DFN;
            if (match[v] == 0 || dfs(match[v])) {
                match[v] = u;
                return true;
            }
        }
        return false;
    }
    vector<int>vc;
    int hungary() {
        memset(match, 0, sizeof match);
        int ans = 0;
        for (int i = 0; i < vc.size(); ++i) {
            ++DFN;
            if (dfs(vc[i])) ans++;
        }
        return ans;
    }
    int col[maxn * maxn * 3];
    void ran(int cur, int which) {
        col[cur] = which;
        book[cur] = DFN;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (book[v] == DFN) continue;
            ran(v, !which);
        }
    }
    void work() {
        memset(first, 0, sizeof first);
        num = 0;
        int to = 0;
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) {
            scanf("%s", str[i] + 1);
        }
        memset(a, 0, sizeof a);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (str[i][j] == '*') {
                    a[i][j] = ++to;
                }
            }
        }
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (a[i][j + 1]) addEdge(a[i][j], a[i][j + 1]);
                if (a[i + 1][j]) addEdge(a[i][j], a[i + 1][j]);
                if (a[i][j - 1]) addEdge(a[i][j], a[i][j - 1]);
                if (a[i - 1][j]) addEdge(a[i][j], a[i - 1][j]);
            }
        }
        memset(col, -1, sizeof col);
        ++DFN;
        for (int i = 1; i <= to; ++i) {
            if (book[i] != DFN) ran(i, 0);
        }
        vc.clear();
        for (int i = 1; i <= to; ++i) {
            if (col[i] == 1) vc.push_back(i);
        }
        cout << to - hungary() << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        int t;
        cin >> t;
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    postman使用教程1-安装与使用
    python3 使用OpenCV计算滑块拼图验证码缺口位置
    httprunner 2.x学习13-自定义校验器(comparator)
    面试题-python3 字符串消消乐,将字符串中相邻相同的字符一起消掉,最后输出消除完成的字符串
    面试题-python3 实现删除字符串中出现次数最少的字符
    面试题-python3 连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组
    httprunner 2.x学习12-在testcase中传递变量(output)
    面试题-python3 找出两个字符串中最大公共子字符串
    httprunner 2.x学习11-命令行参数详解
    mormot2 TRawByteStringStream
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6625296.html
Copyright © 2020-2023  润新知