zoukankan      html  css  js  c++  java
  • hdu 2586 How far away ? 离线LCA

    题目链接:hadu 2586

    题目大意:

    城镇之间互相有道路(双向边),且只存在n-1条边,保证相互可达,求两点
    之间的距离。

    思路:

    转化为LCA裸问题,只需要再一边寻找最近公共祖先的同时,跟
    新当前点到根节点的距离dist即可,那么节点u,v之间的距离为
    dist[u]+dist[v]-2*dist[lca(u,v)];

    代码:

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    const int maxn=40005;
    const int maxm=80005;
    struct enode {
        int to,next,w;
    } edges[maxm];
    struct qnode {
        int to,next,id;
    } query[405];
    //dist[] 节点到根节点的距离
    int head_e[maxn],head_q[maxn],f[maxn],vis[maxn],dist[maxn],res[405];
    int n,m,u,v,w,cnte=0,cntq=0;//n个节点 m个询问
    inline void addedge(int u, int v, int w) {
        edges[cnte].w=w;
        edges[cnte].to=v;
        edges[cnte].next=head_e[u];
        head_e[u]=cnte++;
    }
    inline void addque(int u, int v, int id) {
        query[cntq].id=id;
        query[cntq].to=v;
        query[cntq].next=head_q[u];
        head_q[u]=cntq++;
    }
    inline void init() {
        memset(head_e,-1,sizeof(head_e));
        memset(head_q,-1,sizeof(head_q));
        memset(vis,0,sizeof(vis));
        memset(dist,0,sizeof(dist));
        for(int i=1; i<=n; ++i) f[i]=i;
    }
    int Find(int x) {
        return x==f[x] ? x : f[x]=Find(f[x]);
    }
    void tarjan(int s) {
        vis[s]=1;
        for(int i=head_e[s]; i!=-1; i=edges[i].next) {
            if(!vis[edges[i].to]) {
                dist[edges[i].to]=dist[s]+edges[i].w;//跟新到根的距离
                tarjan(edges[i].to);
                f[edges[i].to]=s;
            }
        }
        for(int i=head_q[s]; i!=-1; i=query[i].next) {
            if(vis[query[i].to]==1) {
                int z=Find(query[i].to);
                //先减去再相加
                res[query[i].id]=dist[s]-dist[z]-dist[z]+dist[query[i].to];
            }
        }
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int t; cin>>t;
        while(t--) {
            cin>>n>>m;
            init();
            for(int i=1; i<n; ++i) {
                cin>>u>>v>>w;
                addedge(u,v,w);
                addedge(v,u,w);
            }
            for(int i=1; i<=m; ++i) {
                cin>>u>>v;
                addque(u,v,i);
                addque(v,u,i);
            }
            dist[1]=0;
            tarjan(1);
            for(int i=1; i<=m; ++i) cout<<res[i]<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    面向对象基础小结
    异常应用场景
    集合应用场景1:迭代器
    集合应用场景2——数据结构
    华为ce交换机 Bridge-Domain NVE
    linux 内核内置模块
    linux bridge 转发 ip
    iptables nat&conntrack
    loopback
    配置集中式网关部署方式的VXLAN示例(静态方式)
  • 原文地址:https://www.cnblogs.com/lemonbiscuit/p/7859413.html
Copyright © 2011-2022 走看看