当前位置: 首页 > news >正文

Codeforces Gym 100015C City Driving 离线LCA

City Driving

题目连接:

http://codeforces.com/gym/100015/attachments

Description

You recently started frequenting San Francisco in your free time and realized that driving in the city is a
huge pain. There are only N locations in the city that interest you, though, and you have decidedtotry
to improve your driving experience. Since you lack a GPS and cannot remember too many di!erent routes,
you wrote down the directions and how long it takes to get between N di!erent pairs of locations (the same
in both directions), ensuring that using only these paths you can get from any location to any other one.
Now you are planning your trip for the weekend and you need to figureoutthefastestwaytogetbetween
Q pairs of locations in the city using only the routes you have written down.

Input

The input consists of multiple test cases. The first line contains a single integer N,3 ! N ! 100,000, the
number of locations of interest and the number of routes you wrotedown.Thenext N lines each contain
three integers u, v,and w (1 ! w ! 1,000), indicating that you have directions from location u to location v
and vice-versa (0-indexed) which take w time. The following line contains a single integer Q,1 ! Q ! 10,000,
the number of pairs of locations you need to compute the travel timefor. Thenext Q lines each contain
two integers u and v, indicating that you should find the minimum time to get from location u to location

v. The input terminates with a line with N = 0. For example:

Output

For each test case, print out Q lines, one for each pair of locations u and v you are finding the fastest routes
for. Each line should simply contain the minimum time it takes to travel from location u to location v.For
example, the correct output for the sample input above would be:

Sample Input

7

0 1 2

0 2 3

1 3 2

2 3 8

2 4 3

3 5 1

1 6 7

3

4 5

0 6

1 2

0

Sample Output

11

9

5

Hint

题意

给你一个n环n边的图,问你两点之间的最短路

题解:

随便找一个环,然后在这个环上随便去掉一条边,然后就比较这个树上的距离小,还是经过这条边的饿距离小

比如你去掉的边是a,b,边权是w,你查询u,v

那么你比较dis(u,v),dis(u,a)+w+dis(b,v),dis(u,b)+w+dis(a,u)就好了

找环上的边,我推荐用并查集

代码

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
struct node
{
    int x,y;
};
vector<node>G[maxn];
int dp[18][maxn*2],dis[maxn],parent[maxn],vis[maxn],pos[maxn],res[maxn];
int n,m,c,num,cnt,si;
int qx=0,qy=0,qv=0;
void init()
{
    qx = qy = qv = 0;
    cnt = num = si = 0;
    memset(dp,0,sizeof(dp));
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(res,0,sizeof(res));
    memset(pos,0,sizeof(pos));
    for(int i=0;i<maxn;i++)
        G[i].clear();
}
int Find(int i)
{
    if(i!=parent[i])
        parent[i]=Find(parent[i]);
    return parent[i];
}
void Union(int i,int j)
{
    int x,y;
    x=Find(i);
    y=Find(j);
    if(x!=y)
        parent[x]=y;
}

void dfs3(int u,int dist)
{
    int i,j;
    vis[u]=1;
    dis[u]=dist;
    pos[u]=cnt;
    res[si]=u;
    dp[0][cnt++]=si++;
    for(i=0;i<G[u].size();i++)
    {
        j=G[u][i].x;
        if(!vis[j])
        {
            dfs3(j,dist+G[u][i].y);
            dp[0][cnt++]=dp[0][pos[u]];
        }
    }
}
void rmq()
{
    int i,j,k;
    for(i=1;(1<<i)<=n;i++)
        for(j=n-1;j>=0;j--)
        {
            k=(1<<(i-1));
            dp[i][j]=dp[i-1][j];
            if(k+j<n)
                dp[i][j]=min(dp[i][j],dp[i-1][j+k]);
        }
}
int cal(int i,int j)
{
    int k;
    if(i<j)swap(i,j);
    k=0;
    while((1<<k)<=(i-j+1))
        k++;
    k--;
    k=min(dp[k][j],dp[k][i-(1<<k)+1]);
    return res[k];
}
int Dis(int u,int v)
{
    int k = cal(pos[u],pos[v]);
    return dis[u]+dis[v]-dis[k]*2;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)break;
        init();
        for(int i=0;i<=n;i++)
            parent[i]=i;
        for(int i=1;i<=n;i++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            x++,y++;
            int p = Find(x),q = Find(y);
            if(p==q){
                qx = x,qy = y,qv = z;
                continue;
            }
            Union(x,y);
            G[x].push_back((node){y,z});
            G[y].push_back((node){x,z});
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                dfs3(i,0);
        n=n*2-1;
        rmq();
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int x,y;scanf("%d%d",&x,&y);
            x++,y++;
            int res = Dis(x,y);
            res = min(res,Dis(x,qx)+Dis(y,qy)+qv);
            res = min(res,Dis(x,qy)+Dis(y,qx)+qv);
            printf("%d\n",res);
        }
    }
}

相关文章:

  • C#中timer类的用法
  • JavaScript基础:数据类型的中的那些少见多怪
  • 负数的二进制表示
  • FreeRADIUS+DaloRADIUS实现PPTP ***高级用户控制+流量控制
  • 利用angular结合translate为项目实现国际化
  • ADT Example
  • 浮现式设计
  • Office365管理员操作手册-1
  • 【设计模式】抽象工厂模式
  • oracle——06表查询中需要注意的一些问题
  • 佛山Uber优步司机奖励政策(1月25日~1月31日)
  • 携程一万亿交易额的市场逻辑
  • java27:集合框架
  • 使用 JavaScript 将网站后台的数据变化实时更新到前端-【知乎总结】
  • 随机IP代理
  • cookie和session
  • FastReport在线报表设计器工作原理
  • happypack两次报错的问题
  • java中具有继承关系的类及其对象初始化顺序
  • mockjs让前端开发独立于后端
  • PAT A1092
  • React as a UI Runtime(五、列表)
  • tweak 支持第三方库
  • 记录一下第一次使用npm
  • 批量截取pdf文件
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • ![CDATA[ ]] 是什么东东
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (4) PIVOT 和 UPIVOT 的使用
  • (9)目标检测_SSD的原理
  • (二)windows配置JDK环境
  • (分布式缓存)Redis分片集群
  • (七)c52学习之旅-中断
  • (强烈推荐)移动端音视频从零到上手(下)
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)shell调试方法
  • (转)视频码率,帧率和分辨率的联系与区别
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .Net mvc总结
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • .NET轻量级ORM组件Dapper葵花宝典
  • .net网站发布-允许更新此预编译站点
  • .NET文档生成工具ADB使用图文教程
  • @ConfigurationProperties注解对数据的自动封装
  • [ vulhub漏洞复现篇 ] ThinkPHP 5.0.23-Rce
  • []sim300 GPRS数据收发程序