poj 1986LCA离线dfs+并查集
题意,给出边和权值,求出两个点间的最短距离。
用离线算法的时候有个地方不知道怎么处理了。在线的本来想用倍增的,但发现倍增算法貌似需要预处理深度而不是权值,不知道怎么处理。套一个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+并查集的更多相关文章
- 【bzoj5183】[Baltic2016]Park 离线+对偶图+并查集
题目描述 在Byteland的首都,有一个矩形围栏围起来的公园.在这个公园里树和访客都以一个圆形表示.公园有四个出入口,每个角落一个(1=左下角,2=右下角,3=右上角,4=左上角).访客能通过这些出 ...
- POJ 1562 Oil Deposits (并查集 OR DFS求联通块)
Oil Deposits Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14628 Accepted: 7972 Des ...
- 距离LCA离线算法Tarjan + dfs + 并查集
距离B - Distance in the Tree 还是普通的LCA但是要求的是两个节点之间的距离,学到了一些 一开始我想用带权并查集进行优化,但是LCA合并的过程晚于离线计算的过程,所以路径长度会 ...
- HDU 5441 离线处理 + 并查集
题意:给n个节点m条带权值边的无向图.然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通:2)其路径的最大权值不能超过询问值. 分析:如果没次询问一次,dfs一次,很可能超时,因此可以用 ...
- poj 1733(带权并查集+离散化)
题目链接:http://poj.org/problem?id=1733 思路:这题一看就想到要用并查集做了,不过一看数据这么大,感觉有点棘手,其实,我们仔细一想可以发现,我们需要记录的是出现过的节点到 ...
- poj 1182 食物链 (并查集)
http://poj.org/problem?id=1182 关于并查集 很好的一道题,开始也看了一直没懂.这次是因为<挑战程序设计竞赛>书上有讲解看了几遍终于懂了.是一种很好的思路,跟网 ...
- 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 ...
- 分珠(dfs+并查集)
1140 分珠 时间限制:500MS 内存限制:65536K提交次数:24 通过次数:18 题型: 编程题 语言: G++;GCC Description 如下图所示,有若干珠子,每颗珠子重量不 ...
- Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)
<题目链接> 题目大意: 有n个房间,每个房间都会有一只老鼠.处于第i个房间的老鼠可以逃窜到第ai个房间中.现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老 ...
随机推荐
- 是什么让javascript变得如此奇妙
What Makes Javascript Weird...and AWESOME -> First Class Functions -> Event-Driven Evironment ...
- 将app接口服务器改为dotnet core承载
昨天我的一个 app 的接口服务器挂掉了,国外的小鸡意外的翻车,连同程序和数据一起,猝不及防.我的服务端程序是 asp.net mvc ,小鸡是 256 M 的内存跑不了 windows 系统,装的 ...
- linux下U盘挂载
linux下挂载U盘 一.Linux挂载U盘:1.插入u盘到计算机,如果目前只插入了一个u盘而且你的硬盘不是scsi的硬盘接口的话,那它的硬件名称为:sda1,可以用"fdisk -l&qu ...
- Unity3D常用代码集合
1.基本碰撞检测代码 function OnCollisionEnter(theCollision : Collision){ if(theCollision.gameObject.n ...
- MySQL、Oracle数据库之操作系统版本选择
玩了快五年的Oracle,期间接触的操作系统大都是linux和aix,其中linux大部分为5.8的红帽子以及centos,oracle可以在上边运行稳定且需要安装其他与oracle相关的rpm包都是 ...
- nstallation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED报这个错的原因???
[2015-06-05 20:37:51 - 05ListView列表控件] ------------------------------ [2015-06-05 20:37:51 - 05ListV ...
- Mysql查询优化器浅析
--Mysql查询优化器浅析 -----------------------------2014/06/11 1 定义 Mysql查询优化器的工作是为查询语句选择合适的执行路径.查询优化器的代码 ...
- Orleans简单配置
Orleans简单配置 这是Orleans系列文章中的一篇.首篇文章在此 话说曾几何时,我第一次看到xml文件,心中闪过一念想:"这<>是什么鬼?"-用ini或者jso ...
- jvm系列 (三) ---锁的优化
锁的优化 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 我的博客目录 锁的四种状态 从低到高,只能升级不能降级 无锁状态 偏向锁 ...
- linux 网络编程
linux网络编程中主要分为服务器和客户端两部分,而网络编程中又分为TCP和UDP两种.TCP(传输控制协议)和UDP(用户数据报协议是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议. ...