题意:给定N个节点一棵树,现在要求询问任意两点之间的简单路径的距离,其实也就是最短路径距离。

析:用LCA问题的Tarjan算法,利用并查集的优越性,产生把所有的点都储存下来,然后把所有的询问也储存下来,然后从树根开始搜索这棵树,

在搜索子树的时候,把并查集的父结点不断更新,在搜索时计算答案,d[i] 表示从根结点到 i 结点的距离,然后分别计算到两个结点的距离,

再减去2倍的根结点到他们公共最近的结点距离,就OK了。不过这个题有个坑人的地方,不用输出那个空行,否则就是PE。

因为这个题询问比较少,所以我们可以用spfa来做。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 4e4 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
struct Edge{
int to, w, next;
};
struct node{
int to, id, next;
};
Edge a[maxn<<1];
node b[405];
int p[maxn], head[maxn<<1], cnt, cnt1, head1[maxn];
int rec[205][3], d[maxn];
bool vis[maxn]; int Find(int x){ return x == p[x] ? x : p[x] = Find(p[x]); } void add(int u, int v, int w){
a[cnt].to = v;
a[cnt].w = w;
a[cnt].next = head[u];
head[u] = cnt++;
} void add1(int u, int v, int id){
b[cnt1].to = v;
b[cnt1].id = id;
b[cnt1].next = head1[u];
head1[u] = cnt1++;
} void Tarjan(int u){
vis[u] = true; for(int i = head1[u]; ~i; i = b[i].next){
int v = b[i].to;
if(vis[v]) rec[b[i].id][2] = Find(v);
} for(int i = head[u]; ~i; i = a[i].next){
int v = a[i].to;
if(!vis[v]){
d[v] = d[u] + a[i].w;
Tarjan(v);
p[v] = u;
}
}
} int main(){
int T; cin >> T;
while(T--){
scanf("%d %d", &n, &m);
for(int i = 0; i <= n; ++i) p[i] = i;
int u, v, w;
cnt = cnt1 = 0;
memset(head, -1, sizeof head);
memset(head1, -1, sizeof head1);
for(int i = 1; i < n; ++i){
scanf("%d %d %d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
for(int i = 0; i < m; ++i){
scanf("%d %d", &u, &v);
add1(u, v, i);
add1(v, u, i);
rec[i][0] = u;
rec[i][1] = v;
}
memset(vis, false, sizeof vis);
d[1] = 0;
Tarjan(1); for(int i = 0; i < m; ++i)
printf("%d\n", d[rec[i][0]] + d[rec[i][1]] - 2*d[rec[i][2]]);
//printf("\n");
}
return 0;
}

第二种写法:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 4e4 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
vector<int> G[maxn], w[maxn], q[maxn], id[maxn];
int d[maxn], p[maxn], ans[205];
bool vis[maxn];
int Find(int x){ return x == p[x] ? x : p[x] = Find(p[x]); } void Tarjan(int u){
vis[u] = true;
for(int i = 0; i < G[u].size(); ++i){
int v = G[u][i];
if(!vis[v]){
d[v] = d[u] + w[u][i];
Tarjan(v);
p[v] = u;
}
} for(int i = 0; i < q[u].size(); ++i){
int v = q[u][i];
if(vis[v]) ans[id[u][i]] = d[u] + d[v] - 2*d[Find(v)];
}
} int main(){
int T;; cin >> T;
while(T--){
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) G[i].clear(), w[i].clear(), q[i].clear(), id[i].clear(), p[i] = i; int u, v, val;
for(int i = 1; i < n; ++i){
scanf("%d %d %d", &u, &v, &val);
G[u].push_back(v);
G[v].push_back(u);
w[u].push_back(val);
w[v].push_back(val);
}
for(int i = 0; i < m; ++i){
scanf("%d %d", &u, &v);
q[u].push_back(v);
q[v].push_back(u);
id[u].push_back(i);
id[v].push_back(i);
}
memset(vis, false, sizeof vis);
d[1] = 0;
Tarjan(1); for(int i = 0; i < m; ++i)
printf("%d\n", ans[i]);
}
return 0;
}

spfa:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 4e4 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
struct node{
int to, w, next;
};
node a[maxn<<1];
int cnt;
int head[maxn];
bool vis[maxn];
int d[maxn];
int q[maxn]; void add(int u, int v, int w){
a[cnt].to = v;
a[cnt].w = w;
a[cnt].next = head[u];
head[u] = cnt++;
} int spfa(int s, int t){
memset(vis, false, sizeof vis);
fill(d, d+n+1, INF);
int front = 0, rear = 0;
q[rear++] = s;
d[s] = 0; while(front < rear){
int u = q[front++];
vis[u] = false; for(int i = head[u]; ~i; i = a[i].next){
int v = a[i].to;
if(d[v] > d[u] + a[i].w){
d[v] = d[u] + a[i].w;
if(!vis[v]) q[rear++] = v, vis[v] = true;
}
}
}
return d[t];
} int main(){
int T; cin >> T;
while(T--){
scanf("%d %d", &n, &m);
int u, v, w;
cnt = 0;
memset(head, -1, sizeof head);
for(int i = 1; i < n; ++i){
scanf("%d %d %d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
while(m--){
scanf("%d %d", &u, &v);
printf("%d\n", spfa(u, v));
}
}
return 0;
}

HDU 2586 How far away ? (LCA,Tarjan, spfa)的更多相关文章

  1. HDU - 2586 How far away ?(离线Tarjan算法)

    1.给定一棵树,每条边都有一定的权值,q次询问,每次询问某两点间的距离. 2.这样就可以用LCA来解,首先找到u, v 两点的lca,然后计算一下距离值就可以了. 这里的计算方法是,记下根结点到任意一 ...

  2. HDU 2586 How far away ? (LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 LCA模版题. RMQ+LCA: #include <iostream> #incl ...

  3. 【HDU 2586 How far away?】LCA问题 Tarjan算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵n个节点的无根树,每条边有各自的权值.给出m个查询,对于每条查询返回节点u到v的最 ...

  4. HDU - 2586 How far away ?(LCA模板题)

    HDU - 2586 How far away ? Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  5. hdu 2586 How far away ?倍增LCA

    hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...

  6. HDU 2586 How far away ?【LCA】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Oth ...

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

    http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的 ...

  8. HDU 2586.How far away ?-离线LCA(Tarjan)

    2586.How far away ? 这个题以前写过在线LCA(ST)的,HDU2586.How far away ?-在线LCA(ST) 现在贴一个离线Tarjan版的 代码: //A-HDU25 ...

  9. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

随机推荐

  1. A20 Android 编译

    cd lichee ./build.sh -p sun7i_android -b wing-sc3075gs cd ../android4.2 . build/envsetup.sh lunch wi ...

  2. asp.net core 初探 二

    今天用@宇内流云大大的jexus 体验一下生产环境的发布,运行. 生产环境: centos 7 jexus 5.8.1 独立版 包含了mono (mono安装真心痛苦……) 开发环境就是昨天的Ubun ...

  3. AppStore审核--17.5

    本文转载至 http://blog.csdn.net/addychen/article/details/39672185 感谢原文作者分享 AppStore审核 为了确保用户理解应用如何使用他们的数据 ...

  4. SAM4E单片机之旅——2、LED闪烁之轮询定时器

    之前我们使用空循环,达到了延迟的目的,但是这样子的延迟比较不精确.现在就使用实时定时器(RTT)来进行更为精确的计时.RTT虽然不是特别通用,在某些单片机上可能没有,但它较为简单. RTT内部有一个计 ...

  5. Java类加载器( 死磕8)

    [正文]Java类加载器(  CLassLoader ) 死磕 8:  使用ASM,和类加载器实现AOP 本小节目录 8.1. ASM字节码操作框架简介 8.2. ASM和访问者模式 8.3. 用于增 ...

  6. Java类加载器(死磕 1-2)

      Java类加载器(  CLassLoader ) 死磕 1.2:  导入 & 类加载器分类 本小节目录 1.导入 1.1. 从class文件的载入开始 1.2. 什么是类加载器 2. JA ...

  7. Redis 单例、主从模式、sentinel 以及集群的配置方式及优缺点对比(转)

    摘要: redis作为一种NoSql数据库,其提供了一种高效的缓存方案,本文则主要对其单例,主从模式,sentinel以及集群的配置方式进行说明,对比其优缺点,阐述redis作为一种缓存框架的高可用性 ...

  8. Win10更新后,IE和Edge以外的浏览器打开网页速度慢的解决方案

    下载修复工具,提取码:you0 以管理员身份运行修复工具,点击“修复” 点击“确定” 提示“修复成功” 参考链接:Win10下极速模式无法打开网页的解决办法_360社区

  9. The PageFactory

    The PageFactory 原文地址:https://github.com/SeleniumHQ/selenium/wiki/PageFactory In order to support the ...

  10. shapes

    接口 shape package shape; public abstract interface shape { public abstract void Draw(); public abstra ...