Code Jam to I/O for Women 2021

Code Jam to I/O for Women 2021

C Introductions Organization 最短路 + 思维

题目大意:

给你 (n) 个经理,编号从 (1)(n)(m) 个非经理,假设 (b)(c) 不认识,但是他们都认识经理 (a) ,那么在 (1s) 内,经理 (a) 可以介绍 (b)(c) 认识,有 (q) 此询问,每次询问 (x)(y) ,问最少经过多少 (s) 他们会相互认识。

题解:

首先求出 (x)(y) 的最短路 (ans) (注意这个最短路上除了起点和终点应该只包括经理的点)

我是希望他们两个的最短路越短越好,所以每一次介绍我希望是缩短的最短路上的点。

假设最短路是 (x - a - b - c - d - e - y)

那么第一秒应该是 (x-a-b) 使得变成 (x - b) ,同时 (c - d - e) 变成 (c - e)

不会有比这个更优的情况了,假设有 (a - d) 直接认识的,那么说明有一条路是 (x - a - ? - d)

那么这条才是最短路,而不是 (x - a - b - c - d)

所以其实求出最短路之后,不断的分成三个一组,进行合并即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int w[maxn][maxn],dis[maxn],n,m,p;
char s[maxn];
queue<int>que;
int bfs(int sx,int sy) {
    while (!que.empty()) que.pop();
    memset(dis, 0, sizeof(dis));
    dis[sx] = 1;
    que.push(sx);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        if (u == sy) return dis[u];
        if (w[u][sy]) return dis[u] + 1;
        for (int j = 1; j <= n; j++) {
            if (dis[j]) continue;
            if (!w[u][j]) continue;
            dis[j] = dis[u] + 1;
            que.push(j);
        }
    }
    return -1;
}
int main() {
    int T;
    scanf("%d", &T);
    for (int cas = 1; cas <= T; cas++) {
        scanf("%d%d%d", &n, &m, &p);
        for (int i = 1; i <= n + m; i++) {
            scanf("%s", s + 1);
            for (int j = 1; j <= n + m; j++) {
                if (s[j] == 'Y') w[i][j] = 1;
                else w[i][j] = 0;
            }
        }
        printf("Case #%d: ", cas);
        for (int i = 1; i <= p; i++) {
            int sx, sy;
            scanf("%d%d", &sx, &sy);
            int res = bfs(sx, sy), ans = 0;
            while (res >= 3) {
                res = res / 3 * 2 + res % 3, ans++;
            }
            if (res < 0) ans = -1;
            printf("%d", ans);
            if (i == p) printf("
");
            else printf(" ");
        }
    }
}
原文地址:https://www.cnblogs.com/EchoZQN/p/14691864.html