POJ1986(LCA应用:求两结点之间距离)
| Time Limit: 2000MS | Memory Limit: 30000K | |
| Total Submissions: 11304 | Accepted: 3985 | |
| Case Time Limit: 1000MS | ||
Description
Input
* Line 2+M: A single integer, K. 1 <= K <= 10,000
* Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms.
Output
Sample Input
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6
Sample Output
13
3
36
学习LCA的好文章:http://taop.marchtea.com/04.04.html
离线:将所有查询输入完毕后再统一输出结果。
在线:查询一个输出一个。 dfs+并查集,离线
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN=;
int n,m,k;
struct Edge{
int to,w;
Edge(){}
Edge(int to,int w)
{
this->to=to;
this->w=w;
}
};
vector<Edge> arc[MAXN]; struct Node{
int to,id;
Node(){}
Node(int to,int id)
{
this->to=to;
this->id=id;
}
};
vector<Node> que[MAXN]; int par[MAXN];
void prep()
{
for(int i=;i<MAXN;i++)
{
d[i]=;
vis[i]=;
par[i]=i;
}
}
int fnd(int x)
{
if(par[x]==x)
{
return x;
}
return par[x]=fnd(par[x]);
}
void unite(int fa,int son)
{
int a=fnd(fa);
int b=fnd(son);
par[b]=a;
} int vis[MAXN],d[MAXN];
int res[MAXN];
void tarjan(int u)
{
vis[u]=;
for(int i=,size=que[u].size();i<size;i++)
{
Node nod=que[u][i];
if(vis[nod.to])
{
int lca=fnd(nod.to);
res[nod.id]=d[nod.to]+d[u]-*d[lca];
}
}
for(int i=,size=arc[u].size();i<size;i++)
{
Edge e=arc[u][i];
if(!vis[e.to])
{
d[e.to]=d[u]+e.w;
tarjan(e.to);
unite(u,e.to);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
prep();
for(int i=;i<=n;i++) arc[i].clear();
for(int i=;i<m;i++)
{
int u,v,w;
scanf("%d %d %d %*c",&u,&v,&w);
arc[u].push_back(Edge(v,w));
arc[v].push_back(Edge(u,w));
}
scanf("%d",&k);
for(int i=;i<k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
que[v].push_back(Node(u,i));
que[u].push_back(Node(v,i));
}
for(int i=;i<=n;i++)
{
if(!vis[i])
{
tarjan(i);
}
}
for(int i=;i<k;i++)
{
printf("%d\n",res[i]);
}
}
return ;
}
模板:RMQ求LCA在线算法(稀疏表实现RMQ)
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
const int MAXN=;
int n,m,k;
struct Edge{
int to,w;
Edge(){}
Edge(int to,int w)
{
this->to=to;
this->w=w;
}
};
vector<Edge> arc[MAXN]; int vs[MAXN+MAXN],depth[MAXN+MAXN],first[MAXN],tot;
int d[MAXN],vis[MAXN];
void dfs(int u,int dep)
{
vis[u]=;
vs[++tot]=u;
depth[tot]=dep;
first[u]=tot;
for(int i=,size=arc[u].size();i<size;i++)
{
Edge e=arc[u][i];
if(!vis[e.to])
{
d[e.to]=d[u]+e.w;
dfs(e.to,dep+);
vs[++tot]=u;
depth[tot]=dep;
}
}
} int dp[MAXN+MAXN][];
void init_st(int size)
{
for(int i=;i<=size;i++) dp[i][]=i;
for(int j=;j<;j++)
{
for(int i=;i<=size;i++)
{
if(i+(<<j)-<=size)
{
int a=dp[i][j-];
int b=dp[i+(<<(j-))][j-];
dp[i][j]=depth[a]<depth[b]?a:b;
}
}
}
}
int rmq_st(int l,int r)
{
int limit=(int)(log(r-l+1.0)/(log(2.0)));
int a=dp[l][limit];
int b=dp[r-(<<limit)+][limit];
return depth[a]<depth[b]?a:b;
} int LCA(int u,int v)
{
if(first[u]>first[v]) swap(u,v);
int id=rmq_st(first[u],first[v]);
return vs[id];
} int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
tot=;
memset(vis,,sizeof(vis));
memset(d,,sizeof(d));
for(int i=;i<=n;i++) arc[i].clear();
for(int i=;i<m;i++)
{
int u,v,w;
scanf("%d %d %d %*c",&u,&v,&w);
arc[u].push_back(Edge(v,w));
arc[v].push_back(Edge(u,w));
}
for(int i=;i<=n;i++)
{
if(!vis[i])
{
dfs(i,);
}
}
init_st(tot);
scanf("%d",&k);
for(int i=;i<k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
int lca=LCA(u,v);
int res=d[u]+d[v]-*d[lca];
printf("%d\n",res);
}
}
return ;
}
POJ1986(LCA应用:求两结点之间距离)的更多相关文章
- hdoj 1869 六度分离【最短路径求两两边之间最长边】
六度分离 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 求两个数之间的质数 -----------基于for循环 算法思想
前端代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.as ...
- js求连个数之间的数字
整理出自项目中一个需求,求两个数之间的数字. const week = function(arr,arr2){ let a=parseInt(arr); let b=parseInt(arr2); l ...
- 「POJ-3608」Bridge Across Islands (旋转卡壳--求两凸包距离)
题目链接 POJ-3608 Bridge Across Islands 题意 依次按逆时针方向给出凸包,在两个凸包小岛之间造桥,求最小距离. 题解 旋转卡壳的应用之一:求两凸包的最近距离. 找到凸包 ...
- 求两点之间距离 C++
求两点之间距离(20 分) 定义一个Point类,有两个数据成员:x和y, 分别代表x坐标和y坐标,并有若干成员函数. 定义一个函数Distance(), 用于求两点之间的距离.输入格式: 输入有两行 ...
- 旋转卡壳求两个凸包最近距离poj3608
#include <iostream> #include <cmath> #include <vector> #include <string.h> # ...
- JavaScript求两个数字之间所有数字的和
这是在fcc上的中级算法中的第一题,拉出来的原因并不是因为有什么好说的,而是我刚看时以为是求两个数字的和, 很显然错了.我感觉自己的文字理解能力被严重鄙视了- -.故拉出来折腾折腾. 要求: 给你一个 ...
- GPS(2)关于位置的3个示例,实时获取GPS定位数据,求两个经纬点距离,邻近某个区域圆时警告
实时获取GPS定位数据 import android.app.Activity; import android.content.Context; import android.location.Loc ...
- js 求两个日期之间相差天数
//求两个日期之间的相差天数 function daysBetween(DateOne, DateTwo) { var OneMonth = DateOne.substring(5, DateOne. ...
随机推荐
- linearLayout 和 relativeLayout的属性区别
LinearLayout和RelativeLayout 共有属性: java代码中通过btn1关联次控件 android:id="@+id/btn1" 控件宽度 android:l ...
- python升级安装后的yum的修复
升级python版本号后,执行yum # yum -y install openssl 提演示样例如以下: There was a problem importing one of the Pytho ...
- CI去掉 URL 中的 index.php
首先,你要清楚自己的 Web 服务器是 Apache,支持 mod_rewrite 查找httpd.conf中是否开启了mod_rewrite.so 然后,在 CI 根目录下新建立一个配置文件,命名为 ...
- php字符串中 转义字符 “ ’‘ ” ’ “” ‘ " \’ ' ' \‘ " " \" '' \ " " 使用
<?php echo $str_string1='甲问:"你在哪里学的PHP?"'; echo "<br />"; echo $str_str ...
- sql查询的日期判断问题
在SQLSERVE中,如果某个数据表的类型被定义成datetime类型,那么数据是包含秒的.这时候如何查询某天的数据呢?新手们可能想:最直接的做法是把时间部分去掉,只取日期部分.于是日期的函数就用上了 ...
- iOS应用上架报错解决
ERROR ITMS-90087: "Unsupported Architectures. The executable for LiveStorage.app/Frameworks/Spe ...
- hadoop 小文件 挂载 小文件对NameNode的内存消耗 HDFS小文件解决方案 客户端 自身机制 HDFS把块默认复制3次至3个不同节点。
hadoop不支持传统文件系统的挂载,使得流式数据装进hadoop变得复杂. hadoo中,文件只是目录项存在:在文件关闭前,其长度一直显示为0:如果在一段时间内将数据写到文件却没有将其关闭,则若网络 ...
- Struts2问题总结
1 如何搭建Struts2开发环境? Struts2 获取 http://struts.apache.org/download.cgi Struts-2.3.16.3-all.zip 创建Web项 ...
- JavaScript及jQuery学习小结
最近几天学习了很多关于JavaScript和jQuery的文章,稍作梳理后,总结如下. 1.jQuery入门系列 环境搭建 只需引用一个jQuery库文件,即可完成jQuery的环境搭建. 选择器 j ...
- 【python】使用python写windows服务
背景 运维windows服务器的同学都知道,windows服务器进行批量管理的时候非常麻烦,没有比较顺手的工具,虽然saltstack和ansible都能够支持windows操作,但是使用起来总感觉不 ...