经出题人同意,决定把此次比赛的题解放在此处供大家参考,如果有纰漏请及时反馈!

1212 刺激战场

题目:http://acm.guet.edu.cn/problem/view/1212.html

思路:

建立二分图:左半部分代表每行,右半部分代表每列。而行顶点i和列顶点j之间的连线就代表图 (i, j) 处有一个玩家。例如对于输入范例可建立以下二分图:

 第二届计算机与信息安全学院程序设计竞赛题解

要求最少操作次数即求该二分图的最小点覆盖集,也就是最大匹配。这里使用了dinic算法求最大匹配,即先将二分图转化为网络流,再进行计算。

#include <bits/stdc++.h>
using namespace std;

const int kMax = 20000 + 10;
const int kInf = 1e9;

struct node {
    int v, cost;
    node(int _v, int _cost) : v(_v), cost(_cost) {}
};

int s, t, n;
int d[kMax];
vector<node> table[kMax];
bool bfs() {
    memset(d, -1, sizeof(d));
    queue<int> q;
    q.push(s);
    d[s] = 0;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = 0;i < table[u].size();++ i) {
            int v = table[u][i].v;
            if (table[u][i].cost > 0 && d[v] == -1) {
                q.push(v);
                d[v] = d[u] + 1;
            }
        }
    }
    return d[t] != -1;
}
int dfs(int u, int flow) {
    if(u == t) return flow;
    int res = 0;
    for (int i = 0;i < table[u].size();++ i) {
        int v = table[u][i].v;
        if (table[u][i].cost > 0 && d[v] == d[u] + 1) {
            int tmp = dfs(v, min(flow, table[u][i].cost));
            flow -= tmp;
            table[u][i].cost -= tmp;
            res += tmp;
            for (int j = 0;j < table[v].size();++ j) {
                if (table[v][j].v == u) {
                    table[v][j].cost += tmp;
                    break;
                }
            }
            if (flow == 0) break;
        }
    }
    if (res == 0) d[u] = -1;
    return res;
}
int dinic() {
    int res = 0;
    while (bfs()) { res += dfs(s, kInf); }
    return res;
}

int main() {
    int m, a, b;
    scanf("%d%d", &n, &m);
    for (int i = 0;i < m;++ i) {
        scanf("%d%d", &a, &b);
        table[a].push_back({b + n, 1});
        table[b + n].push_back({a, 0});
    }
    s = 0;
    t = n + n + 1;
    for (int i = 1;i <= n;++ i) {
        table[s].push_back({i, 1});
        table[i].push_back({s, 0});
        table[i + n].push_back({t, 1});
        table[t].push_back({i + n, 0});
    }
    printf("%d\n", dinic());
    return 0;
}
View Code

相关文章: