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 ...
随机推荐
- dsp-asic-fpga
DSP是在模拟信号变换成数字信号以后进行高速实时处理的专用处理器,它采用的是哈佛设计,即数据总线和地址总线分开,使程序和数据分别存储在两个分开的空间,允许取指令和执行指令完全重叠,也就是说在执行上一条 ...
- PS 魔法棒
魔术棒工具是通过选取图像中颜色相近或大面积单色区域的像素来制作选区,魔术棒用于纯色背景中较多. 容差数值越大,选择出的选区就越大,容差越小,对颜色差别的要求也就越严格,选择出的选区也就越小 按住shi ...
- gdb调试段错误及使用
在编程调试中,经常出现段错误,此时可用gdb调试.具体方法为注册段错误信号处理函数,在处理函数中启动gdb.具体代码如下: void segv_handler(int no) { ]; ]; FILE ...
- 通过串口工具下发指令的Python脚本
前言 最近一段时间在测试物联网相关的App自动化,涉及通过串口工具给硬件设备下发指令. 使用的串口工具:SecureCRT 解决办法 通过引用Python的第三方库:serial,通过编写Python ...
- flume topology design . tier num 分层数目
32:+:1 x:1 x<=8 https://flume.apache.org/FlumeUserGuide.html#flume-topology-design Flume topology ...
- tornado安全应用之用户认证
在这个例子中,我们将只通过存储在安全cookie里的用户名标识一个人.当某人首次在某个浏览器(或cookie过期后)访问我们的页面时,我们展示一个登录表单页面.表单作为到LoginHandler路由的 ...
- Windows10搭建FTP服务器
配置FTP服务器步骤: 第一步: 打开控制面板--->选择程序--->启动或关闭Windows功能--->勾选FTP服务器等.如下图: 第二步: 右键此电脑--->点击管理-- ...
- linux系统上安装svn服务器 环境linux+nginx+svnserver
系统:Ubuntu 12.04 64位 lnmp环境 集成软件:PHP5.4.27.Nginx1.6.0.MySQL5.5.37 阿里云server svnserver有2种执行方式:独立server ...
- Mac终端操作SVN指令
1.将文件checkout到本地目录 svn checkout path(path是服务器上的目录) 例如:svn checkout svn://192.168.1.1/pro/domain ...
- Ubuntu 12.04安装grub2过程中出错怎么办【转】
本文转载自:https://zhidao.baidu.com/question/491448169666671012.html 其实是可以不用优盘启动的.但使用优盘没有风险.你的系统虽然出现==不能安 ...