HDU 2874 LCA离线算法

Connections between cities

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4477    Accepted Submission(s): 1284

Problem Description

After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city. For most of roads had been totally destroyed during the war, there might be no path between two cities, no circle exists as well.
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.

Input

Input consists of multiple problem instances.For each instance, first line contains three integers n, m and c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n represents the number of cities numbered from 1 to n. Following m lines, each line has three integers i, j and k, represent a road between city i and city j, with length k. Last c lines, two integers i, j each line, indicates a query of city i and city j.

Output

For each problem instance, one line for each query. If no path between two cities, output “Not connected”, otherwise output the length of the shortest path between them.

Sample Input

5 3 2

1 3 2

2 4 3

5 2 3

1 4

4 5

Sample Output

Not connected

6

题意:

第一行三个数n, m, q即为n个点,m条边,q次询问。下面m行为x, y, z即编号为x和y点之间有边权值为z,下面q次询问,每行x, y即询问x,y两点最短距离。

若x, y之间有边输出最短距离,否则输出Not connected。

思路:

第一次看到这个题想到是最短路径类型的题,提交上wa了,仔细看了一下题,发现给出的图是无环图也就是树或者森林,那么这个题很容易就知道是lca了。

假设x, y两点在一棵树上,它们的最近公共祖先为z。设x, y所在树的根结点为w,dis[x]即为点x到其树根的距离,那么x, y之间最短距离很明显就是

dis[x]+dis[y]-2*dis[z]。 那么用tarjan算法深搜一下就行了。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <iostream>
 6 using namespace std;
 7 #define N 10005
 8
 9 struct node{
10     int y, w;
11 };
12
13 int f[N];
14 int father[N];
15 int dis[N];
16 int visited[N];
17 int ans[1000005];            //注意ans数组的大小,我就RE了很长时间。。。
18 vector<node>ve[N], q[N];
19 int n;
20
21 void init(){
22     for(int i=0;i<=n;i++){
23         ve[i].clear();
24         q[i].clear();
25         f[i]=i;
26         father[i]=i;
27     }
28     memset(dis,0,sizeof(dis));
29     memset(visited,0,sizeof(visited));
30     memset(ans,-1,sizeof(ans));
31 }
32
33 int findroot(int p){
34     int r=p;
35     while(r!=father[r])
36     r=father[r];
37     return r;
38 }
39 void lca(int u,int d,int ff){
40     int v, i;
41     node p;
42     visited[u]=1;dis[u]=d;f[u]=ff;
43     for(i=0;i<ve[u].size();i++){
44         p=ve[u][i];
45         v=p.y;
46         if(!visited[v]){
47             lca(v,d+p.w,ff);
48             father[v]=u;
49         }
50     }
51     for(i=0;i<q[u].size();i++){
52         p=q[u][i];
53         int id=p.w;
54         v=p.y;
55         if(visited[v]&&f[v]==f[u]){
56             ans[id]=dis[u]+dis[v]-2*dis[findroot(v)];     //findroot(v)而不是findroot(u),想一想为什么
57         }
58     }
59 }
60 main()
61 {
62     int m, Q;
63     int x, y, z;
64     int i, j, k;
65     node p;
66     while(scanf("%d %d %d",&n,&m,&Q)==3){
67         init();
68         for(i=0;i<m;i++){
69             scanf("%d %d %d",&x,&y,&z);
70             p.y=y;p.w=z;
71             ve[x].push_back(p);
72             p.y=x;
73             ve[y].push_back(p);
74         }
75         for(i=1;i<=Q;i++){
76             scanf("%d %d",&x,&y);
77             p.y=y;p.w=i;
78             q[x].push_back(p);
79             p.y=x;
80             q[y].push_back(p);
81         }
82         for(i=1;i<=n;i++){
83             if(!visited[i])
84             lca(i,0,i);
85         }
86         for(i=1;i<=Q;i++){
87             if(ans[i]==-1) printf("Not connected\n");
88             else printf("%d\n",ans[i]);
89         }
90     }
91 }

HDU 2874 LCA离线算法,布布扣,bubuko.com

时间: 2024-12-23 04:56:39

HDU 2874 LCA离线算法的相关文章

HDU 2874 LCA离线算法 tarjan算法

给出N个点,M条边,Q次询问 Q次询问每两点之间的最短距离 典型LCA 问题   Marjan算法解 #include "stdio.h" #include "string.h" struct Edge { int to,next,len; }edge[20010]; struct Ques { int to,next,index; }ques[2000010]; int head[10010],q_head[10010],f[10010],dis[10010];

HDU 2586 LCA离线算法 tarjan算法

LCA tarjan算法模板题 题意:给一个无根树,有q个询问,每个询问两个点,问两点的距离. 用tarjan离线算法算出每个询问的两点的最近公共祖先 ans[i]=dis[x[i]]+dis[y[i]]-2*dis[z[i]]; //  x[i],y[i]分别存储每次询问的两点,z[i]存储这两点的最近公共祖先 #include "stdio.h" #include "string.h" int tot,n,m; int f[40010],x[40010],y[4

HDU 4547 LCA倍增算法

CD操作 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1111    Accepted Submission(s): 297 Problem Description 在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录. 这里我们简化一下问题,假设只有一个根目录,

HDU 2874 Connections between cities(LCA离线算法实现)

http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 求两个城市之间的距离. 思路: LCA题,注意原图可能不连通. 如果不了解离线算法的话,可以看我之前博客写的解释http://www.cnblogs.com/zyb993963526/p/7295894.html 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cs

LCA离线算法Tarjan详解

离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点为u,与它有关的点为v,如果v已经访问过了,那么它们的LCA就是find(v).如果v还没有访问,那就不用管它. ②对该点的子节点继续dfs,需要注意的是,dfs完之后需要需要p[v]=u,将v点并到其父亲节点上. 1 void LCA(int u) 2 { 3 vis[u]=1; 4 for(in

Closest Common Ancestors---poj1470(LCA+离线算法)

题目链接:http://poj.org/problem?id=1470 题意是给出一颗树,q个查询,每个查询都是求出u和v的LCA:    以下是寻找LCA的预处理过程: void LCA(u){ for(u的每个儿子v) { LCA(v); union(u,v);//并到一个集合中去 } visit[u]=1; for(查询中u的每个儿子v) { if(visit[v]) u,v的最近公共祖先是father[getfather(v)]; } } 详细解释   图文详解  本题可以使用预处理的方

Hdu 2874(LCA)

题目链接 Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5037    Accepted Submission(s): 1399 Problem Description After World War X, a lot of cities have been seriously d

HDU 2874 LCA转RMQ+并查集

点击打开链接 题意:问两个城市是否相连,不相连输出Not connected,否则输出两个城市间的最短距离 思路:用并查集判断两个城市的连通性,如果联通则做法和LCA一样,但是注意的一点是地图不连通的话,我们要将所有点都建起来,就要加一个模拟的点,将所有图串起来,很好处理的,看一下就会了 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include

1128 - Greatest Parent---LightOj(LCA+离线算法)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1128 给你一颗树,树的每个节点都有一个权值,树根是节点0,权值为1,树中每个节点的权值都是大于父节点的权值的: 然后给出每个节点的父节点以及该节点的权值:有Q个询问,每个询问有两个数u和val,求u的祖先中权值>=val的最大祖先,就是离u最远的那个>=val的祖先的节点: 数的范围较大有5w个Q,1w个n,所以我们不能直接模拟,也许这1w个节点是一串下来的,那么复杂度就变成了nQ