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,问你消灭掉所有老 ...
随机推荐
- 43. leetcode 459. Repeated Substring Pattern
459. Repeated Substring Pattern Given a non-empty string check if it can be constructed by taking a ...
- amd和cmd区别
作者:玉伯 链接:https://www.zhihu.com/question/20351507/answer/14859415 来源:知乎 著作权归作者所有,转载请联系作者获得授权. AMD 是 R ...
- Python Socket 简单聊天室2
上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
- 【思维】【水】 南阳oj 喷水装置(一)
描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中心的半径为实数Ri(0<Ri<15)的圆被湿润,这有充足的喷水装置i(1& ...
- ECharts的简单使用
ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻 ...
- NOIP 2002 提高组 字串变换
题目描述 已知有两个字串 A, B 及一组字串变换的规则(至多6个规则): A1 -> B1 A2 -> B2 规则的含义为:在 A$中的子串 A1 可以变换为 B1.A2 可以变换为 B ...
- 关于Spring总结
关于Spring总结 Spring引入 传统的基于mvc的项目框架结构:Entity / dao / service / action 简单用户访问流程:/user.action ----> T ...
- 关于 Overtrue 的拼音库 overtrue/pinyin 为何 travis 为 error【社交系统研发日记十】
什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+(简称TS+).社交系统 ...
- python ——面向对象进阶
1.staticmethod和classmethod staticmethod 静态方法: 让类里的方法,直接被类调用,就像正常的函数一样 宝宝,男 博博,女 海娇,男 海燕,女 海东,男 海峰,男 ...
- 集合set
一.集合的作用 知识点回顾:可变类型是不可hash类型,不可变类型是可hash类型 作用:去重,关系运算 定义:可以包含多个元素,用逗号分割,集合的元素遵循三个原则: 1.每个元素必须是不可变类型(可 ...