题意,给出边和权值,求出两个点间的最短距离。

用离线算法的时候有个地方不知道怎么处理了。在线的本来想用倍增的,但发现倍增算法貌似需要预处理深度而不是权值,不知道怎么处理。套一个rmq的模板吧,用来处理权值的时候。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std; const int NN=100010; int n,m;
vector<pair<int,int> > edge[NN],qe[NN];
vector<int> q1,q2; int p[NN];
int find(int x)
{
if (p[x]!=x) p[x]=find(p[x]);
return p[x];
} int sum=0,ans[NN],dis[NN];
bool vis[NN]={0};
void lca(int u,int fa)
{
p[u]=u;
for (int i=0; i<edge[u].size(); i++)
{
int v=edge[u][i].first;
if (v==fa) continue;
dis[v]=dis[u]+edge[u][i].second;
lca(v,u);
p[v]=u;
}
vis[u]=true;
if (sum==m) return;
for (int i=0; i<qe[u].size(); i++)
{
int v=qe[u][i].first;
if (vis[v])
ans[qe[u][i].second]=dis[u]+dis[v]-2*dis[find(v)];
}
} int main()
{
int u,v,w;
char str[4];
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++)
{
edge[i].clear();
}
for (int i=1; i<=m; i++)
{
scanf("%d%d%d%s",&u,&v,&w,str);
edge[u].push_back(make_pair(v,w));
edge[v].push_back(make_pair(u,w));
}
scanf("%d",&m);
for (int i=0; i<m; i++)
{
scanf("%d%d",&u,&v);
qe[u].push_back(make_pair(v,i));
qe[v].push_back(make_pair(u,i));
ans[i]=0;
}
dis[1]=0;
lca(1,0);
for (int i=0; i<m; i++) printf("%d\n",ans[i]);
return 0;
}

在线的dfs+rmq模板套一个:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std; const int NN=50000; int n,rt;
vector<pair<int,int> > edge[NN]; int depth=0;
int bn=0,b[NN*2]; //深度序列
int f[NN*2]; //对应深度序列中的结点编号
int p[NN]; //结点在深度序列中的首位置
int dis[NN]; //结点到根的距离
void dfs(int u,int fa)
{
int tmp=++depth;
b[++bn]=tmp; f[tmp]=u; p[u]=bn;
for (int i=0; i<edge[u].size(); i++)
{
int v=edge[u][i].first;
if (v==fa) continue;
dis[v]=dis[u]+edge[u][i].second;
dfs(v,u);
b[++bn]=tmp;
}
} int dp[NN*2][20];
void rmq_init(int n) //以深度序列做rmq
{
for (int i=1; i<=n; i++) dp[i][0]=b[i];
int m=floor(log(n*1.0)/log(2.0));
for (int j=1; j<=m; j++)
for (int i=1; i<=n-(1<<j)+1; i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int l,int r)
{
int k=floor(log((r-l+1)*1.0)/log(2.0));
return min(dp[l][k],dp[r-(1<<k)+1][k]);
} int lca(int a,int b)
{
if (p[a]>p[b]) swap(a,b);
int k=rmq(p[a],p[b]);
return f[k];
} int main()
{
int m,u,v,w;
char str[4];
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) edge[i].clear();
while (m--)
{
scanf("%d%d%d%s",&u,&v,&w,str);
edge[u].push_back(make_pair(v,w));
edge[v].push_back(make_pair(u,w));
}
rt=1; dis[rt]=0;
dfs(1,0);
rmq_init(bn);
scanf("%d",&m);
while (m--)
{
scanf("%d%d",&u,&v);
printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]);
}
return 0;
}

poj 1986LCA离线dfs+并查集的更多相关文章

  1. 【bzoj5183】[Baltic2016]Park 离线+对偶图+并查集

    题目描述 在Byteland的首都,有一个矩形围栏围起来的公园.在这个公园里树和访客都以一个圆形表示.公园有四个出入口,每个角落一个(1=左下角,2=右下角,3=右上角,4=左上角).访客能通过这些出 ...

  2. POJ 1562 Oil Deposits (并查集 OR DFS求联通块)

    Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14628   Accepted: 7972 Des ...

  3. 距离LCA离线算法Tarjan + dfs + 并查集

    距离B - Distance in the Tree 还是普通的LCA但是要求的是两个节点之间的距离,学到了一些 一开始我想用带权并查集进行优化,但是LCA合并的过程晚于离线计算的过程,所以路径长度会 ...

  4. HDU 5441 离线处理 + 并查集

    题意:给n个节点m条带权值边的无向图.然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通:2)其路径的最大权值不能超过询问值. 分析:如果没次询问一次,dfs一次,很可能超时,因此可以用 ...

  5. poj 1733(带权并查集+离散化)

    题目链接:http://poj.org/problem?id=1733 思路:这题一看就想到要用并查集做了,不过一看数据这么大,感觉有点棘手,其实,我们仔细一想可以发现,我们需要记录的是出现过的节点到 ...

  6. poj 1182 食物链 (并查集)

    http://poj.org/problem?id=1182 关于并查集 很好的一道题,开始也看了一直没懂.这次是因为<挑战程序设计竞赛>书上有讲解看了几遍终于懂了.是一种很好的思路,跟网 ...

  7. POJ 1182 食物链(并查集拆点)

    [题目链接] http://poj.org/problem?id=1182 [题目大意] 草原上有三种物种,分别为A,B,C A吃B,B吃C,C吃A. 1 x y表示x和y是同类,2 x y表示x吃y ...

  8. 分珠(dfs+并查集)

    1140 分珠 时间限制:500MS  内存限制:65536K提交次数:24 通过次数:18 题型: 编程题   语言: G++;GCC Description 如下图所示,有若干珠子,每颗珠子重量不 ...

  9. Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)

    <题目链接> 题目大意: 有n个房间,每个房间都会有一只老鼠.处于第i个房间的老鼠可以逃窜到第ai个房间中.现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老 ...

随机推荐

  1. git push解决办法: ! [remote rejected] master -> master (pre-receive hook declined)

    前天准备上传一个project到GitLab上,但是试了很多次都上传不上去,报错如下: ! [remote rejected] master -> master (pre-receive hoo ...

  2. for’ loop initial declarations are only allowed in C99 mode

    今天做南邮编程在线的编程题,编程首先计算Fibonacci数列1,1,2,3,5,8,13,21,......的前n项(n不超过40)存入一维整型数组f中,再按%12d的格式输出每项的值,每6项换一行 ...

  3. 求m区间内的最小值

    洛谷P1440 求m区间内的最小值 ............................................................................... 以上 ...

  4. centos 7 运行Quartus ii 17.0 标准版,下载程序时遇到错误error (209053): unexpected error in jtag server -- error code 89

    对于错误error (209053): unexpected error in jtag server -- error code 89,它产生的原因在于,在linux系统下,Quartus ii的驱 ...

  5. Oracle外键需要建索引吗?

    关于Oracle中的外键,首先要说明一下. 1. 除非已定义了父表主键或唯一键约束,否则oracle将不允许创建子表的外键约束. 2. 在定义外键约束时,oracle不会自动创建索引,所以必须手动在与 ...

  6. 剑指OFFER(百度笔试)——二叉树的子结构

    百度软件开发实习生笔试: 1.模拟短作业优先调度算法,计算平均等待时间,例如输入[0,2,4,8]表示四个作业分别是第0s到.第2s到.第4s到.第8s到.[2,1,6,3]表示四个作业的运行时间. ...

  7. 原来,负载均衡可以这样用,多核CPU可以这样用

    负载均衡作为一个处理高并发,大流量的访问的业务场景,已经几乎是常识性的知识了. 而本文的意义在于需求:由于大流量请求,导致服务无法正常响应,在不增加购买机器成本的场景下,如何提高服务器的业务处理能力? ...

  8. Flask-RESTful接口开发学习笔记一:实现简单的GET请求

    1.首先安装需要依赖的第三方包: (1):Flask (2):Flask-RESTful 如何安装就不在啰嗦,pip也好,下载到本地再安装也好,看你随意. 2.我们先实现GET请求. Q:什么是GET ...

  9. [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示

    javascript面向对象编程方式,对于初学者来说,会比较难懂. 要学会面向对象以及使用面向对象编程,理解对象的创建在内存中的表示,至关重要. 首先,我们来一段简单的对象创建代码 var obj = ...

  10. fodera20安装后的配置

    最近安装了Fedora 20 64bit,以下是一些优化配置,使之更适合国人使用. 1,安装gnome-tweak-tool设置工具 Fedora 19自带的系统设置工具十分简单,一些重要的地方都不能 ...