牛客国庆集训派对Day6 J-最短路 (任意两点间最短路径问题)

链接:https://www.nowcoder.com/acm/contest/206/J
来源:牛客网
 

题目描述

给一个连通图,每次询问两点间最短路。每条边的长度都是1。

输入描述:

第一行两个整数n和m,表示图的点数和边数(1≤ n≤ 100000, 1≤ m≤ n+100)。
接下来m行每行两个整数a和b,表示一条边(1≤ a, b≤ n)。保证没有自环和重边。保证图连通。
接下来一个整数q表示询问的个数(1≤ q≤ 100000)。
接下来q行每行两个整数a和b表示询问a和b之间的最短路。

输出描述:

每个询问输出一行表示答案。

示例1

输入

复制

4 5
1 2
2 3
1 4
4 3
2 4
4
1 4
1 2
2 4
1 3

输出

复制

1
1
1
2

 

解题思路:任意查询最短路问题,如果每次查询都跑一次最短路,铁定超时。考虑优化,题目说了,最多只有100个环,因此我们可以把这些环单独提取出来单独处理即可。

 

我们先对图求一遍最小生成树,把会形成环的边先单独提取出来。然后求LCA,把树上答案先计算出来。然后我们再把所有环边加进原图,然后对每一个环边的点求一次最短路径(边权为1,BFS就好了)。然后更新答案就好了。

 

图上的最短路径为 dis[i][u]+dis[i][v],i表示从第i个环边上的点出发,到u,v的最短路

树上的最短路径为 deep[u]+deep[v]-2*deep[LCA(u,v)]

取min最好了。

 

这里的常数复杂的较大,用树链剖分求LCA会快很多,数据肯定很多链。

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
using namespace std;
typedef unsigned long long ll;
inline void scan_d(int &ret) 
{
    char c; 
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    { 
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

const int MAXN=100005;
vector G[MAXN];
int N,M,Q;

/****树链剖分求LCA****/
int sz[MAXN];
int son[MAXN];
int top[MAXN];
int dep[MAXN];
int pre[MAXN];

void dfs1(int u, int fa)
{
    pre[u]=fa;
    sz[u]=1;
    int& maxs = son[u]=-1;
    dep[u] = dep[fa] + 1;
    for(int i=0;isz[maxs])
            maxs=v;
    }
}

void dfs2(int u,int tp){
    top[u]=tp;
    if(son[u]!=-1)
        dfs2(son[u],tp);
    for(int i=0;i que;
void bfs(int s){
    for(int i=1;i<=N;i++){
        in[i]=0;
        dis[cnt][i]=0x3f3f3f3f;
    }
    que.push(s);
    dis[cnt][s]=0;
    while(!que.empty()){
        int tp=que.front();
        que.pop();
        if(in[tp])
            continue;
        in[tp]=1;
        for(int i=0;idis[cnt][tp]+1){
                dis[cnt][v]=dis[cnt][tp]+1;
                que.push(v);
            }
        }
    }
    cnt++;
}

vector > hb;

int main(){
    scan_d(N);
    scan_d(M);
    
    for(int i=0;i<=N;i++)
        fa[i]=i;
    
    int u,v;
    int fx,fy;
    for(int i=0;i

 

 

 

 

 

你可能感兴趣的:(ACM,-,最短路径,————ACM相关————,——图论相关——)