hdu 5093 Battle ships(最大流)

题意: 。。。。


对每行来说, 如果两个*之间没有被#隔开的话, 就把它们看成是一个联通块,因为它们之间只能选一个点, 对列也是这样, 然后对所有*, 在它所属的行块和列块连一条流量为1边, 表示如果选了这个点, 那么它所在的行块和列块都不能选了, 然后从源点向每个行块连边, 并从每个列块向汇点连边, 跑下最大流就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

#define mnx 55
#define N 3020
#define E 500030
#define inf 0x3f3f3f3f
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)

struct edge {
    int u, v, cap, flow, nxt;
    void set(int _u, int _v, int _cap, int _flow, int _nxt) {
        u = _u, v = _v, cap = _cap, flow = _flow, nxt = _nxt;
    }
};

struct dinic {
    int s, t, fst[N], cc, d[N], cur[N];
    edge e[E];
    void init() {
        memset(fst, -1, sizeof(fst));
        cc = 0;
    }
    void add(int u, int v, int cap) {
        e[cc].set(u, v, cap, 0, fst[u]), fst[u] = cc++;
        e[cc].set(v, u, 0, 0, fst[v]), fst[v] = cc++;
    }
    bool bfs() {
        memset(d, -1, sizeof(d));
        queue<int> q;
        d[s] = 0, q.push(s);
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(int i = fst[u]; ~i; i = e[i].nxt) {
                int v = e[i].v;
                if(d[v] == -1 && e[i].cap > e[i].flow) {
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
        return d[t] != -1;
    }
    int dfs(int x, int a) {
        if(x == t || a == 0) return a;
        int f, flow = 0;
        for(int &i = cur[x]; ~i; i = e[i].nxt) {
            if(i == inf) i = fst[x];
            if(i == -1) break;
            int v = e[i].v;
            if(d[v] == d[x] + 1 && (f = dfs(v, min(a, e[i].cap - e[i].flow))) > 0) {
                a -= f, e[i ^ 1].flow -= f;
                e[i].flow += f, flow += f;
                if(!a) break;
            }
        }
        return flow;
    }
    int go(int s, int t) {
        this -> s = s, this -> t = t;
        int flow = 0;
        while(bfs()) {
            memset(cur, 0x3f, sizeof(cur));
            flow += dfs(s, inf);
        }
        return flow;
    }
}go;
int n, m;
char g[mnx][mnx];

int id[mnx][mnx];
int S, T;
int a, b;
bool vis[mnx][mnx];

void getR() {
    a = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            if(vis[i][j] || g[i][j] != '*') continue;
            int k = j;
            ++a;
            while(k <= m && g[i][k] != '#') {
                id[i][k] = a;
                vis[i][k] = 1;
                ++k;
            }
        }
    }
}
void getC() {
    b = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= m; ++i) {
        for(int j = 1; j <= n; ++j) {
            if(vis[j][i] || g[j][i] != '*') continue;
            int k = j;
            ++b;
            while(k <= n && g[k][i] != '#') {
                vis[k][i] = 1;
                if(g[k][i] == 'o') {
                    ++k;
                    continue;
                }
                go.add(id[k][i], a + b, 1);
                ++k;
            }
        }
    }
}
int main() {
    int cas;
    scanf("%d", &cas);
    while(cas--) {
        go.init();
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i)
            scanf("%s", g[i] + 1);
        getR();
        getC();
        S = 0, T = a + b + 1;
        for(int i = 1; i <= a; ++i)
            go.add(S, i, 1);
        for(int i = 1; i <= b; ++i)
            go.add(i + a, T, 1);
        printf("%d\n", go.go(S, T));
    }
    return 0;
}



你可能感兴趣的:(最大流,dinic)