HDU 2586 How far away ? (LCA,Tarjan, spfa)
题意:给定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)的更多相关文章
- HDU - 2586 How far away ?(离线Tarjan算法)
1.给定一棵树,每条边都有一定的权值,q次询问,每次询问某两点间的距离. 2.这样就可以用LCA来解,首先找到u, v 两点的lca,然后计算一下距离值就可以了. 这里的计算方法是,记下根结点到任意一 ...
- HDU 2586 How far away ? (LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 LCA模版题. RMQ+LCA: #include <iostream> #incl ...
- 【HDU 2586 How far away?】LCA问题 Tarjan算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵n个节点的无根树,每条边有各自的权值.给出m个查询,对于每条查询返回节点u到v的最 ...
- HDU - 2586 How far away ?(LCA模板题)
HDU - 2586 How far away ? Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & ...
- hdu 2586 How far away ?倍增LCA
hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...
- 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 ...
- HDU 2586 How far away ?(LCA在线算法实现)
http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的 ...
- HDU 2586.How far away ?-离线LCA(Tarjan)
2586.How far away ? 这个题以前写过在线LCA(ST)的,HDU2586.How far away ?-在线LCA(ST) 现在贴一个离线Tarjan版的 代码: //A-HDU25 ...
- HDU 2586 How far away ?(LCA模板 近期公共祖先啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...
随机推荐
- C递归算法与栈的分析,非全然二叉树遍历分析---ShinePans
对于递归,这里面的分析最好当然是用图形的方式来分析了.这里来总结一下 1.首先对于栈的理解: 先进后出,后进先出 先进后出 2.在进行非全然二叉树的存储之后,我们要做的是对其 ...
- python中的and和or(转载)
python中的and和or 4.6. and 和 or 的特殊性质在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返回布尔值:而是,返回它们实际进行比较的值之一 ...
- Java面向对象编程(一)
由于常常将Java和C++面向对象编程的原则搞乱,所以这次把相关要点分别总结一下,本文主要总结Java面向对象编程. 面向对象编程的三大特性是:继承性(inheritance), 多态性(polymo ...
- 【leetcode】Jump Game I, II 跳跃游戏一和二
题目: Jump Game I: Given an array of non-negative integers, you are initially positioned at the first ...
- 问题 “cell 出栈 selectBox 已选的图标,被释放掉,再次进入屏幕时,没有了已选图标 ” 解决方案
如何 去解决 列表里面的selectBox已选情况,在滑出屏幕后被清除的问题. 我来在这里 详细说明一下, 在cell里面写一个方法,去专门修复滑出后,又滑进来 图标被冲刷掉的cell. 在 ...
- [Phoenix] 四、加盐表
摘要: 在密码学中,加盐是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串.这个在散列中加入字符串的方式称为“加盐”.其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情 ...
- BitMapFactory.decodeFile 总是返回NULL的原因之一
之前碰到过,顺便记录下来,如果出现这种情况,首先看看是否有对这个文件的读权限.
- emoji字符不能插入MySQL数据库,提示“'\xF0\x9F\x98\x84' for column 'XXXX' at row 1”
从网络中取下的数据解析后不能插入数据库,提示某个字段有问题,问题提示如下: SQLException: Incorrect string value: '\xF0\x9F\x98\x84' for c ...
- git基本操作---持续更新(2017-08-11)
git 强制push $ git push -u origin master -f 查看本地标签 $ git tag 打标签并添加备注 $ git tag 20170811 -m"图片保存多 ...
- Java 获取当前日期和时间
原文地址:http://www.blogjava.net/parable-myth/archive/2013/01/17/394364.html 有三种方法: 方法一:用java.util.Date类 ...