hdu2874 LCA在线算法

Connections between cities

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

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条边,不存在环,也就是说要么是树要么就是多棵树,c次查询,问x到y的距离。

思路:

由于可能查询的2个点不相连,可以给同一棵树中的点一个标记,如果查询的时候2个点不属于同一棵树,那肯定就不相连。

/*
 * Author:  sweat123
 * Created Time:  2016/7/13 10:56:50
 * File Name: main.cpp
 */
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define key_value ch[ch[root][1]][0]
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 10010;
struct node{
    int to;
    int val;
    int next;
}edge[MAXN*2];
int dp[MAXN*2][20],ver[MAXN*2],vis[MAXN],dfn[MAXN*2],first[MAXN],pre[MAXN];
ll dis[MAXN];
int n,m,q,tot,ind,mark[MAXN];
void add(int x,int y,int z){
    edge[ind].to = y;
    edge[ind].val = z;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
void dfs(int rt,int dep,int flag){
    vis[rt] = 1;
    ver[++tot] = rt;
    dfn[tot] = dep;
    first[rt] = tot;
    mark[rt] = flag;
    for(int i = pre[rt]; i != -1; i = edge[i].next){
        int t = edge[i].to;
        if(!vis[t]){
            dis[t] = dis[rt] + edge[i].val;
            dfs(t,dep+1,flag);
            ver[++tot] = rt;
            dfn[tot] = dep;
        }
    }
}
void rmq(){
    for(int i = 1; i <= tot; i++){
        dp[i][0] = i;
    }
    for(int i = 1; i < 20; i++){
        for(int j = 1; j + (1 << i) - 1 <= tot; j++){
            int x = dp[j][i-1];
            int y = dp[j+(1<<(i-1))][i-1];
            if(dfn[x] > dfn[y]){
                dp[j][i] = y;
            } else{
                dp[j][i] = x;
            }
        }
    }
}
int askrmq(int x,int y){
    x = first[x];
    y = first[y];
    if(x > y)swap(x,y);
    int k = (int)(log(y - x + 1) * 1.0 / log(2.0));
    int l = dp[x][k];
    int r = dp[y - (1<<k) + 1][k];
    if(dfn[l] > dfn[r])return r;
    else return l;
}
int main(){
    while(~scanf("%d%d%d",&n,&m,&q)){
        ind = tot = 0;
        memset(vis,0,sizeof(vis));
        memset(pre,-1,sizeof(pre));
        for(int i = 1; i <= m; i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        int cnt = 0;
        memset(mark,0,sizeof(mark));
        for(int i = 1; i <= n; i++){
            if(!vis[i])dfs(i,1,++cnt);
        }
        rmq();
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            if(mark[x] != mark[y]){
                printf("Not connected\n");
            } else{
                int tp = ver[askrmq(x,y)];
                ll ans = dis[x] - dis[tp] + dis[y] - dis[tp];
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
时间: 2024-11-07 01:22:40

hdu2874 LCA在线算法的相关文章

hihocoder1069最近公共祖先&#183;三(LCA在线算法--DFS+RMQ-ST)

树上任意两点的最近祖先,必定就是这两个节点的最短路径上深度最小的那个点. 例如:下图中,节点7和5,其最短路径为7--4--1--5, 这条路径上深度最小的点为节点1,其深度为1.节点1即为节点7和5的LCA. 因此,要找到任意两个节点的LCA,只需要先找到上述最短路径,再找到最短路径中深度最小的点.而这下面所述LCA在线算法所做的事. LCA在线算法描述(以上图为例): 1.获得“最短路径”(并不是真正的一条路径,包含其他节点,但不影响算法的正确性) 采用DFS遍历整棵树,得到以下数据: (1

LCA在线算法ST算法

求LCA(最近公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ(区间最大最小值编号)的,不懂的可以这里学习一些 而求LCA就是把树通过深搜得到一个序列,然后转化为求区间的最小编号. 比如说给出这样一棵树. 我们通过深搜可以得到这样一个序列: 节点ver 1 3 1 2 5 7 5 6 5 2 4 2 1 (先右后左) 深度R 1 2 1 2 3 4 3 4 3

LCA在线算法详解

LCA(最近公共祖先)的求法有多种,这里先介绍第一种:在线算法. 声明一下:下面的内容参考了http://www.cnblogs.com/scau20110726/archive/2013/05/26/3100812.html. 在线算法就是利用了DFS和RMQ两种算法,它先是预处理好所有情况,然后根据输入输出答案,在输入比较多的时候用比较好. 上面两张图介绍了在线算法的做法,要理解并不难,下面附上实现代码: 1 /******************************* 2 dfs实现代

lca 在线算法 zoj 3195

题目链接:Design the city 题目大意是对给定3点,求这三个点只之间的最短距离.三个点两两组合求lca:dis[u]+dis[v]-dis[lca];将三个组合值相加除以2即为答案. RMQ算法学习:http://blog.csdn.net/liang5630/article/details/7917702 对于lca->RMQ的转化,可以参看巨巨写的ppt. 欧拉序列:euler[N]; 深度序列:depth[N]; #include <iostream> #include

HDU 2586 How far away ?(LCA在线算法实现)

http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的距离,然后只要计算出两点的LCA,这样一来答案就是distance[u]+distance[v]-2distance[LCA]. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #includ

LCA最近公共祖先 在线算法和离线算法 模板

原理讲解:http://dongxicheng.org/structure/lca-rmq/ 在线算法模板: /** LCA在线算法O(nlogn) 主函数调用: init(); tot=0,dir[1]=0; dfs(1,1); ST(2*n-1); int lca=LCA(u,v); */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #in

hdu 3078(LCA的在线算法)

Network Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 847    Accepted Submission(s): 347 Problem Description The ALPC company is now working on his own network system, which is connecting all

LCA(倍增在线算法) codevs 2370 小机房的树

codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计

最近公共祖先(LCA):离线&amp;在线算法

问题:求两个结点的最近公共祖先(即在树中的公共祖先中高度最低的祖先),下面介绍两种适用于不同场景的算法. Hiho15:离线Tarjan算法 基本思想 Tarjan算法适用于离线批量处理多个查询请求.基本思想是以深度优先搜索的顺序访问这颗树,给这棵树的结点染色,一开始所有结点都是白色的,而当第一次经过某个结点的时候,将它染成灰色,而当第二次经过这个结点的时候--也就是离开这棵子树的时候,将它染成黑色. 这样做的意义,举例说明,当我们深度优先搜索到A结点时,我们发现A结点和B结点是我们需要处理的一