NC19814 最短路(LCA)

最短路

https://ac.nowcoder.com/acm/problem/19814

题目链接

题意:

题解:










AC代码

/*
    Author : zzugzx
    Lang : C++
    Blog : blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9+7;
//const int mod = 998244353;
const double eps = 1e-10;
const double pi = acos(-1.0);
const int maxn = 1e6+10;
const ll inf = 0x3f3f3f3f;
const int dir[][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
int n, m, depth[maxn], f[maxn][50];
int from[maxn], to[maxn << 1], nxt[maxn << 1], cnt = 1, Log[maxn], From[maxn];
bool vis[maxn], used[maxn];
//链式前向星加边
void addEdge (int u, int v) {
    From[++cnt] = u, to[cnt] = v, nxt[cnt] = from[u], from[u] = cnt;
}
//计算深度&计算祖先
void dfs (int u, int fa) {
    depth[u] = depth[fa] + 1;
    vis[u] = 1;
    for (register int i = 1; i <= Log[n]; ++i) {
        if ((1 << i) > depth[u]) break;
        f[u][i] =  f[f[u][i - 1]][i - 1];
    }
    for (register int i = from[u]; i; i = nxt[i]) {
        ll v = to[i];
        if (vis[v]) continue;
        used[i] = used[i ^ 1] = 1;
        f[v][0] = u;
        dfs (v, u);
    }
}
//计算LCA
inline int LCA (int x, int y) {
    if (depth[x] < depth[y]) swap(x, y);
    //我们默认x为更深的那个点
    for(register int i = Log[n] ; i >= 0 ; --i)
        if(depth[x] - (1 << i) >= depth[y]) x = f[x][i];
    //将x跳到和y同一深度上
    if (x == y) return x;
    for (register int i = Log[n]; i >= 0; --i)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    //一起向上跳
    return f[x][0];
    //不难看出,此时两个点均在其LCA的下方,往上跳一次即可
}
void init(){
    Log[0] = -1;
    for (register int i = 1, u, v; i <= m; ++i) {
        cin >> u >> v;
        addEdge (u, v); addEdge(v, u);
        Log[i] = Log[i >> 1] + 1;
    }
    Log[n] = Log[n >> 1] + 1;
    dfs(1, 0);
}
int dist(int p , int q){return depth[p] + depth[q] - 2 * depth[LCA(p , q)];}
int ans[maxn],a[maxn],b[maxn],dis[maxn], Q, q[maxn], h, t;
void bfs(int s){
    for (int i = 1; i <= n; i++)dis[i] = inf;
    dis[s] = 0;
    h = t = 0;
    q[++h] = s;
    while (t < h) {
        int u = q[++t];
        for (int i = from[u]; i; i = nxt[i]){
            int v = to[i];
            if (dis[v] > dis[u] + 1)
                dis[v] = dis[u] + 1, q[++h] = v;
        }
    }
    for (int i = 1; i <= Q; i++)
        ans[i] = min(ans[i], dis[a[i]] + dis[b[i]]);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
//  freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    cin >> n >> m;
    init();
    cin >> Q;
    for (int i = 1; i <= Q; i++){
        cin >> a[i] >> b[i];
        ans[i] = dist(a[i], b[i]);
    }
    int num = 0;
    for (int i = 2; i <= cnt; i++)
        if(!used[i]) {
            used[i] = used[i ^ 1] = 1;
            bfs(From[i]);
            num++;
            if(num > 101) break;
        }
    for (int i = 1; i <= Q; i++)
        cout << ans[i] << endl;
    return 0;
}
每日一题 文章被收录于专栏

每日一题

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 12:31
以前小时候我最痛恨出轨、偷情的人,无论男女,为什么会出轨?现在我成了自己最讨厌的人,没想到分享的东西在牛客会被这么多人看,大家的评价都很中肯,我也认同,想过一一回复,但我还是收声了,我想我应该说说这件事,这件事一直压在我心里,是个很大的心结,上面说了人为什么出轨,我大概能明白了。我们大一下半年开始恋爱,开始恋爱,我给出了我铭记3年的承诺,我对她好一辈子,我永远不会背叛,我责任心太重,我觉得跟了我,我就要照顾她一辈子,我们在一起3年我都没有碰过她,她说往东我就往东,她说什么我做什么,她要我干什么,我就干什么!在学校很美好,中途也出过一些小插曲,比如男闺蜜、男闺蜜2号等等等。但我都强迫她改掉了,我...
牛客刘北:两个缺爱的人是没有办法好好在一起的,但世界上哪有什么是非对错?你后悔你们在一起了,但是刚刚在一起的美好也是真的呀,因为其他人的出现,你开始想要了最开始的自己,你的确对不起自己,21岁的你望高物远,你完全可以不谈恋爱,去过你想要的生活,你向往自由,在一起之后,你要想的不是一个人,而是两个人,你不是变心了,就像你说的,你受够了,你不想包容了,冷静几天是你最优的选择,爱人先爱己。
社会教会你的第一课
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务