zoukankan      html  css  js  c++  java
  • [cf1495D]BFS Trees

    记$d_{G}(x,y)$表示无向图$G$中从$x$到$y$的最短路,设给定的图为$G=(V,E)$,$T$为其生成树,$E_{T}$为$T$的边集

    下面,考虑计算$f(x,y)$——

    首先,对于一棵树$T$,$z$在$x$到$y$的路径上(包括$x$和$y$)当且仅当$d_{T}(x,z)+d_{T}(z,y)=d_{T}(x,y)$

    同时,由于$T$的性质,上述这三项都与$d_{G}$中相同,即等价于$d_{G}(x,z)+d_{G}(z,y)=d_{G}(x,y)$

    由于这与$T$无关,即可确定$T$中在$x$到$y$的路径上的点(满足上述条件的$z$)

    进而,当点数不等于$d_{G}(x,y)+1$(也即有多条最短路)必然无解,否则显然最短路存在且唯一

    反过来,也可以确定不在$x$到$y$路径上的点$z$,考虑在$T$中以$x$或$y$为根,$z$的父亲$fa$必然是同一个节点,且显然也满足以下性质——

    $(z,fa)in E_{T}$、$d_{T}(x,z)=d_{T}(x,fa)+1$且$d_{T}(y,z)=d_{T}(y,fa)+1$

    类似的,第一个条件写作$(z,fa)in E$,后两个条件也可以等价的写作$d_{G}$

    此时,当确定每一个不在$x$到$y$路径上点的$fa$时,将所有的$(z,fa)$以及$x$到$y$的最短路上所有边构成$E_{T}$,由于最短路的性质,这必然合法

    因此,最终答案即所有不在$x$到$y$路径上节点$fa$的个数乘积,预处理最短路后计算复杂度为$o(m)$

    最短路使用bfs即$o(nm)$,总复杂度为$o(n^{2}m)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 405
     4 #define M 605
     5 #define mod 998244353 
     6 struct Edge{
     7     int nex,to;
     8 }edge[M<<1];
     9 queue<int>q;
    10 int E,n,m,x,y,head[N],vis[N],d[N][N];
    11 void add(int x,int y){
    12     edge[E].nex=head[x];
    13     edge[E].to=y;
    14     head[x]=E++;
    15 }
    16 void bfs(int st){
    17     memset(vis,0,sizeof(vis));
    18     q.push(st);
    19     vis[st]=1;
    20     while (!q.empty()){
    21         int k=q.front();
    22         q.pop();
    23         for(int i=head[k];i!=-1;i=edge[i].nex)
    24             if (!vis[edge[i].to]){
    25                 d[st][edge[i].to]=d[st][k]+1;
    26                 q.push(edge[i].to);
    27                 vis[edge[i].to]=1;
    28             }
    29     }
    30 }
    31 int main(){
    32     scanf("%d%d",&n,&m);
    33     memset(head,-1,sizeof(head));
    34     for(int i=1;i<=m;i++){
    35         scanf("%d%d",&x,&y);
    36         add(x,y);
    37         add(y,x);
    38     }
    39     for(int i=1;i<=n;i++)bfs(i);
    40     for(int i=1;i<=n;i++){
    41         for(int j=1;j<=n;j++){
    42             int tot=0,ans=1;
    43             for(int k=1;k<=n;k++)
    44                 if (d[i][k]+d[k][j]==d[i][j])tot++;
    45                 else{
    46                     int s=0;
    47                     for(int l=head[k];l!=-1;l=edge[l].nex)
    48                         if ((d[i][k]==d[i][edge[l].to]+1)&&(d[j][k]==d[j][edge[l].to]+1))s++;
    49                     ans=1LL*ans*s%mod;
    50                 }
    51             if (tot!=d[i][j]+1)ans=0;
    52             printf("%d ",ans);
    53         }
    54         printf("
    ");
    55     }
    56 }
    View Code
  • 相关阅读:
    JavaScript内置函数
    JavaScript内置函数
    javascript入门之算术乘法表
    第三章 3 python运算符的优先级
    第三章 2 pyhon中的运算符
    第三章 1 input输入函数
    第二章 5 python中的注释
    第二章 4 数据类型的转换
    第二章 3 数据类型
    第二章 2 python中的标识符和保留字
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14731845.html
Copyright © 2011-2022 走看看