• HDU-2586-How far away(LCA Tarjan离线算法)


    链接:https://vjudge.net/problem/HDU-2586

    题意:

    勇气小镇是一个有着n个房屋的小镇,为什么把它叫做勇气小镇呢,这个故事就要从勇气小镇成立的那天说起了,
    修建小镇的时候,为了让小镇有特色,镇长特地只修了n-1条路,并且规定说,所有在勇气小镇的村民,每一次出门必须规划好路线, 
    路线必须满足在到达终点之前绝对不走回头路。每个人都要这样,不然那个人就不配在小镇生活下去,因为他没有这个勇气。
    事实上,这并不能算一项挑战,因为n-1条路已经连通了每户人家,不回头地从起点到终点,只是一个时间上的问题。
    由于小镇上的福利特别好,所以小懒入住了这个小镇,他规划了m次的行程,每次从L房屋到R房屋,他想问你他每次从L房屋到R房屋需要走多远的路。

    思路:

    Tarjan离线算法, 第i个查询的最短路为dis[s[i]]+dis[e[i]]-2*dis[fas[i]]

    代码:

    #include <iostream>
    #include <memory.h>
    #include <string>
    #include <istream>
    #include <sstream>
    #include <vector>
    #include <stack>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <set>
    #include <iterator>
    #include <cstring>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 4e4+10;
    struct Node
    {
        int from_, to_, dist_;
        Node(int from, int to, int dist):from_(from), to_(to), dist_(dist){}
    };
    vector<Node> G[MAXN];
    int fa[MAXN], dis[MAXN];
    int vis[MAXN], fas[MAXN];
    int s[MAXN], e[MAXN];
    int n, m, l, r, v;
    int root, res;
    
    int Get_F(int x)
    {
        if (fa[x] == x)
            return x;
        fa[x] = Get_F(fa[x]);
        return fa[x];
    }
    
    void Merge(int u, int v)
    {
        int tv = Get_F(v);
        int tu = Get_F(u);
        if (tv != tu)
            fa[v] = u;
    }
    
    void Tarjan(int u)
    {
        vis[u] = 1;
        for (int i = 1;i <= m;i++)
        {
            if (s[i] == u && vis[e[i]] == 1)
                fas[i] = Get_F(e[i]);
            if (e[i] == u && vis[s[i]] == 1)
                fas[i] = Get_F(s[i]);
        }
        for (int i = 0;i < G[u].size();i++)
        {
            Node node = G[u][i];
            if (!vis[node.to_])
            {
                dis[node.to_] = dis[node.from_] + node.dist_;
                Tarjan(node.to_);
                Merge(node.from_, node.to_);
            }
        }
    }
    
    void init()
    {
        for (int i = 1;i <= n;i++)
        {
            G[i].clear();
            fa[i] = i;
        }
        memset(vis, 0, sizeof(vis));
        memset(dis, 0, sizeof(vis));
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t;
        cin >> t;
        while (t--)
        {
            cin >> n >> m;
            init();
            for (int i = 1;i < n;i++)
            {
                cin >> l >> r >> v;
                G[l].emplace_back(l, r, v);
                G[r].emplace_back(r, l, v);
            }
            for (int i = 1;i <= m;i++)
            {
                cin >> l >> r;
                s[i] = l;
                e[i] = r;
            }
            dis[1] = 0;
            Tarjan(1);
            for (int i = 1;i <= m;i++)
            {
                cout << dis[s[i]]+dis[e[i]]-2*dis[fas[i]] << endl;
            }
        }
    
        return 0;
    }
    

      

  • 相关阅读:
    SNF软件开发机器人-子系统-功能-启用大按钮样式如何配置
    SNF软件开发机器人-子系统-功能-数据录入方式
    SNF软件开发机器人-子系统-功能-功能类型(普通表改为树型表)
    SNF软件开发机器人-子系统-导出-导入功能-多人合作时这个功能经常用到
    SQL SERVER数据库删除LOG文件和清空日志的方案
    打不开磁盘“I:xxx.vmdk”或它所依赖的某个快照磁盘
    chrome浏览器解决跨域问题
    AngularJS判断checkbox/复选框是否选中并实时显示
    非常全的VsCode快捷键
    Oracle&SQLServer中实现跨库查询
  • 原文地址:https://www.cnblogs.com/YDDDD/p/10837293.html
Copyright © 2020-2023  润新知