zoukankan      html  css  js  c++  java
  • 【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("
    ");
        }
    }
    
  • 相关阅读:
    在MathType如何让括号随内容自动调整大小的技巧
    对于MathType中公式与文字错位的问题怎么解决
    怎样批量修改MathType公式格式
    你与论文达人只差一个MathType的距离
    公式达人必杀技,你会几招?
    如何用MathType快速输入公式
    openfire数据库mysql配置
    thinkphp 操作mssql2008
    phpstudy+php5.2+mssql2008
    thinkphp openfire 添加用户 骨架
  • 原文地址:https://www.cnblogs.com/tudouuuuu/p/14524027.html
Copyright © 2011-2022 走看看