CodeForces 173B Chamber of Secrets 二分图+最短路

题目链接:

http://codeforces.com/problemset/problem/173/B

题意:

给你一个n*m的地图,现在有一束激光从左上角往左边射出,每遇到‘#’,你可以选择光线往四个方向射出,或者什么都不做,问最少需要多少个‘#’往四个方向射出才能使关系在n行往右边射出。

题解:

以行和列建二分图,如果str[i][j]=='#',则从i节点到j节点建一条双向边,权值都为1。然后对二分图跑一遍最短路。

代码:

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

const int maxn = 2222;

vector<int> G[maxn];
char str[maxn][maxn];
int n, m;

int inq[maxn], d[maxn];
int spfa() {
    queue<int> Q;
    memset(inq, 0, sizeof(inq));
    memset(d, 0x7f, sizeof(d)); int ma = d[0];
    d[1] = 0; inq[1] = 1; Q.push(1);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (d[v] > d[u] + 1) {
                d[v] = d[u] + 1;
                if (!inq[v]) inq[v]=1,Q.push(v);
            }
        }
    }
    if (d[n] >= ma) return -1;
    return d[n];
}

void init() {
    for (int i = 0; i <= n + m + 1; i++) G[i].clear();
}

int main() {
    while (scanf("%d%d", &n, &m) == 2 && n) {
        init();
        for (int i = 1; i <= n; i++) scanf("%s", str[i] + 1);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (str[i][j] == '#') {
                    G[i].push_back(j + n);
                    G[j + n].push_back(i);
                }
            }
        }
        int ans = spfa();
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/fenice/p/5549287.html