zoukankan      html  css  js  c++  java
  • CF1495D

    题意

    定义一个图的生成树是以节点 (s) 为根的 BFS 树,当且仅当对任意节点(t),图中 (s)(t) 的最短路径长度等于树上 (s)(t) 的最短路径长度。

    对于一个图,定义 (f(x, y)) 为该图满足「同时是以节点 (x) 为根的 BFS 树和以节点 (y) 为根的 BFS 树」的生成树数量。

    给出一个 (n) 个节点 (m) 条边的无向连通图,请对每对 (i), (j), 计算 (f(i, j))(998244353) 取模的值。

    (nle 400, m le 600)

    题解

    (n)(m)都很小,故分别计算每个(f(x,y))

    (dis(x,y))代表(x)(y)的最短路上的长度(结点数),这个用bfs即可得到,(O(n^2m))

    对于每个(x,y),如果(x)(y)的最短路多于1条,显然有(f(x,y)=0)。即对于结点(z),如果(dis(x,z)+dis(z,y)-1=dis(x,y)),那么(z)必定在(x)(y)的最短路上,这样的(z)数量恰好为(dis(x,y))

    对于不在最短路上的结点,与它相邻的结点都是bfs树上潜在的父亲。设结点(i),与其相邻的结点为(j),如果有

    [dis(i,x)=dis(j,x)+1 \ dis(i,y)=dis(j,y)+1 ]

    那么(j)在bfs树中就可以成为(i)的父亲。同样在bfs树中如果(j)要成为(i)的父亲,必须满足上面的条件。

    如果为每个结点都任选一个父亲,那么它们恰好能够构成一颗bfs树。故总共可能的bfs树就是每个结点(除了(x)(y)路径上的结点)的父亲数的乘积。

    总时间复杂度(O(n^2m))

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 1e3 + 10;
    const int M = 998244353;
    const double eps = 1e-5;
    
    vector<int> np[N];
    int dis[N][N];
    int cnt[N];
    bool flag[N];
    int ans[N][N];
    
    void clear(int n) {
    	for(int i = 1; i <= n; i++) {
    		cnt[i] = 0;
    		flag[i] = 0;
    	}
    }
    
    int main() {
    	IOS;
    	int n, m;
    	cin >> n >> m;
    	for(int i = 1; i <= m; i++) {
    		int u, v;
    		cin >> u >> v;
    		np[u].push_back(v);
    		np[v].push_back(u);
    	}
    	for(int i = 1; i <= n; i++) {
    		queue<int> q;
    		q.push(i);
    		dis[i][i] = 1;
    		while(!q.empty()) {
    			int cur = q.front();
    			q.pop();
    			for(int nt : np[cur]) {
    				if(dis[i][nt]) continue;
    				dis[i][nt] = dis[i][cur] + 1;
    				q.push(nt);
    			}
    		}
    	}
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			int num = 0;
    			clear(n);
    			for(int k = 1; k <= n; k++) {
    				if(dis[i][k] + dis[k][j] - 1 == dis[i][j]) {
    					num++;
    					flag[k] = 1;
    				}
    				for(int nt : np[k]) {
    					if(dis[nt][i] == dis[k][i] + 1 && dis[nt][j] == dis[k][j] + 1)
    						cnt[nt]++;
    				}
    			}
    			if(num != dis[i][j]) continue;
    			ll res = 1;
    			for(int k = 1; k <= n; k++) {
    				if(flag[k]) continue;
    				res = res * cnt[k] % M;
    			}
    			ans[i][j] = res;
    		}
    	}
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cout << ans[i][j] << " 
    "[j == n];
    		}
    	}
    }
    
  • 相关阅读:
    时间戳(1532249295.179) 转日期格式(2018/07/22 16:48:15 179)
    iscroll.js右侧可滑动的菜单,点击每个菜单都会出现本菜单的详情
    canvas绘制的文字如何换行
    移动端H5页面禁止长按复制和去掉点击时高亮
    一列宽度不缩放,一列宽度弹性缩放,且超出后显示省略号
    js钩子机制(hook)
    mCustomScrollbar.js 漂亮的滚动条插件 适应内容自动更新
    axios.js 实例 -----$.ajax的替代方案
    用 async/await 来处理异步实例
    C#入门经典第18章-WEB编程
  • 原文地址:https://www.cnblogs.com/limil/p/15302397.html
Copyright © 2011-2022 走看看