【CF1496F】BFS Trees(BFS树的性质积累)

题目链接:https://codeforces.com/contest/1496/problem/F
官方题解:https://codeforces.com/blog/entry/88533

题解提炼

(dist(x,y)) 为从点 (x) 到点 (y) 所经过的点的个数。

有两点性质:

  1. 对于点 (z),当 (dist(x,z)+dist(y,z)-1=dist(x,y)),那么点 (z) 应当是在从 (x)(y) 的最短路上。
    特别的,当这样的点的个树超过 (dist(x,y)) 个时,那么 (x)(y) 作为根节点的BFS树同构必定不存在,举个例子,注意点 (1) 和点 (3)
5 6
1 2
2 3
1 4
4 3
1 5 
3 5
  1. 对于其他不在从 (x)(y) 的最短路的点 (u),要存在相邻的点 (v),使得 (dist(x,v)=dist(x,u)-1) 并且 (dist(y,v)=dist(y,u)-1)
    这一部分证明过程比较复杂请看官方题解。

AC代码

#include <bits/stdc++.h>

typedef long long ll;
#define llinf 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define SZ(x) (int)x.size()
#define mp make_pair
#define pii pair<int, int>
#define vi vector<int>
#define pb push_back

using namespace std;

const int MAXN = 400 + 10;
const int MAXM = 600 + 10;
const int mod = 998244353;

struct Edge {
    int to, nex;
} e[MAXM << 1];

int head[MAXN], tol;

void addEdge(int u, int v) {
    e[tol].to = v, e[tol].nex = head[u], head[u] = tol, tol++;
}


int dis[MAXN][MAXN];

void bfs(int s) {
    queue<int> q;
    dis[s][s] = 1;
    q.push(s);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = head[u]; ~i; i = e[i].nex) {
            int v = e[i].to;
            if (!dis[s][v]) {
                dis[s][v] = dis[s][u] + 1;
                q.push(v);
            }
        }
    }
}

ll res[MAXN][MAXN];

int main() {
    int n, m;
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= n; i++) head[i] = -1;

    while (m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        addEdge(u, v), addEdge(v, u);
    }
    for (int i = 1; i <= n; i++) bfs(i);

    for (int x = 1; x <= n; x++) {
        for (int y = x; y <= n; y++) {

            int cnt = 0;
            for (int i = 1; i <= n; i++) {
                if (dis[x][i] + dis[y][i] - 1 == dis[x][y]) cnt++; // i int the path of x to y
            }
            ll ans = 1;
            if (cnt > dis[x][y]) ans = 0;
            for (int u = 1; u <= n; u++) {
                if (dis[x][u] + dis[y][u] - 1 != dis[x][y]) {
                    int fg = 0;
                    for (int i = head[u]; ~i; i = e[i].nex) {
                        int v = e[i].to;
                        if (dis[x][v] == dis[x][u] - 1 && dis[y][v] == dis[y][u] - 1) fg++;
                    }
                    ans = ans * fg % mod;
                    if (!ans) break;
                }
            }
            res[x][y] = res[y][x] = ans;
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            printf("%d ", res[i][j]);
        }
        printf("
");
    }
}
原文地址:https://www.cnblogs.com/tudouuuuu/p/14524027.html