第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先。因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟,可以先将u,v,和其最近公共祖先保存到数组,然后再求结果,为什么不能直接保存其结果了。如果只保存结果的话,保存查询操作就可以节约1/3的内存,所以基本可以过了。

代码如下:

方法一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 10100;
vector<pair<int,int> >tree[maxn],query[maxn];
int father[2][maxn],res[1000010],dis[maxn],vis[maxn]; void init(int n)
{
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(res,-1,sizeof(res));
for( int i = 0; i <= n; i++){
tree[i].clear();
query[i].clear();
father[0][i] = father[1][i] = i;
}
}
int find(int x,int k){
if( x != father[k][x])
return father[k][x] = find(father[k][x],k);
return father[k][x];
}
void LCA(int u){
vis[u] = 1; pair<int,int>x;
int i,size = query[u].size();
for( i = 0; i < size; i++){
x = query[u][i];
if( vis[x.first])
res[x.second] = dis[u] + dis[x.first] - 2*dis[find(x.first,0)];
} size = tree[u].size();
for( i = 0; i < size; i++){
x = tree[u][i];
if( !vis[x.first] ){
dis[x.first] = dis[u] + x.second;
LCA(x.first);
union_set(x.first,u,0);
}
}
}
void union_set(int x,int y,int k){
x = find(x,k);
y = find(y,k);
if ( x != y)
father[k][x] = father[k][y];
}
int main()
{
int n,m,c;
int u,v,d;
int i;
// freopen("in.txt","r",stdin);
while( ~scanf("%d%d%d",&n,&m,&c) ){
init(n);
while( m-- ){
scanf("%d%d%d",&u,&v,&d);
union_set(u,v);
tree[u].push_back(make_pair(v,d));
tree[v].push_back(make_pair(u,d));
}
for( i = 0; i < c; i++){
scanf("%d%d",&u,&v);
if( find(u,1) != find(v,1))continue;
query[u].push_back(make_pair(v,i));
query[v].push_back(make_pair(u,i));
}
for( i = 1; i <= n; i++){
if( !vis[i] )
LCA(i);
}
for( i = 0; i < c; i++)
if( res[i] == -1)puts("Not connected");
else printf("%d\n",res[i]);
}
return 0;
}

方法二:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std;
const int maxn = 10100;
int anc[maxn],dis[maxn],deep[maxn],vis[maxn],fa[maxn];
vector<pair<int,int> >tree[maxn];
void init(int n)
{
memset(vis,0,sizeof(vis));
for( int i = 1; i <= n; i++){
fa[i] = i;
tree[i].clear();
}
}
void dfs(int u,int now_fa,int now_anc,int now_deep,int now_len)
{
fa[u] = now_fa;
anc[u] = now_anc;
vis[u] = u;
deep[u] = now_deep;
dis[u] = now_len;
for( int i = 0; i < tree[u].size() ; i++)
{
pair<int,int>x = tree[u][i];
if( !vis[x.first] )
dfs(x.first,u,now_anc,now_deep+1,now_len+x.second);
}
}
int find(int x,int y){
if( x == y)return x;
if( deep[x] > deep[y])
return find(fa[x],y);
else return find(x,fa[y]);
}
int main()
{
int n,m,c;
int u,v,d;
int i;
while( ~scanf("%d%d%d",&n,&m,&c)){
init(n); while( m-- ){
scanf("%d%d%d",&u,&v,&d);
tree[u].push_back(make_pair(v,d));
tree[v].push_back(make_pair(u,d));
}
for( i = 1; i <= n; i++ )
if(!vis[i])
dfs(i,-1,i,0,0);
for( i = 0; i < c; i++){
scanf("%d%d",&u,&v);
if(anc[u] != anc[v])puts("Not connected");
else printf("%d\n",dis[u]+dis[v] - 2*dis[find(u,v)]);
}
}
return 0;
}

HDU2874 Connections between cities 最近公共祖先的更多相关文章

  1. hdu-2874 Connections between cities(lca+tarjan+并查集)

    题目链接: Connections between cities Time Limit: 10000/5000 MS (Java/Others)     Memory Limit: 32768/327 ...

  2. [HDU2874]Connections between cities

    思路:LCA裸题.本来是帮pechpo调错,结果自己写了半天… 设$dis_x$是点$x$到根结点距离,不难想到两点$u$.$v$之间最短距离等于$dis_u+dis_v-dis_{LCA(u,v)} ...

  3. [hdu2874]Connections between cities(LCA+并查集)

    题意:n棵树,求任意两点的最短距离. 解题关键:并查集判断两点是否位于一棵树上,然后求最短距离即可.此题可以直接对全部区间直接进行st表,因为first数组会将连接的两点的区间表示出来. //#pra ...

  4. LCA(最近公共祖先)——Tarjan

    什么是最近公共祖先? 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵树上距离最近的公共祖先节点. ...

  5. hdu 2874 Connections between cities [LCA] (lca->rmq)

    Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  6. Connections between cities

    Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...

  7. hdu 2874 Connections between cities(st&rmq LCA)

    Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  8. 最近公共祖先(LCA)模板

    以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...

  9. LCA(最近公共祖先)专题(不定期更新)

    Tarjan(离线)算法 思路: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5 ...

随机推荐

  1. Windbg程序调试系列-索引篇

    最近整理了一下Windbg程序调试系列的文章,做个了索引贴,方便大家查询.搜索: Windbg程序调试系列1-常用命令说明&示例 Windbg程序调试系列1-Mex扩展使用总结 Windbg程 ...

  2. 关于Unity 中对UGUI制作任务系统的编程

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  3. ASP.NET Core on K8S深入学习(3)Deployment

    上一篇<部署过程解析与安装Dashboard>中我们了解K8S的部署过程,这一篇我们来了解一下K8S为我们提供的几种应用运行方式:Deployment.DaemonSet与Job,它们是K ...

  4. spring-boot项目的docker集成化部署(一)

    目录 spring-boot项目的docker集成化部署 前言 基本思路与方案 基本步骤 准备源码 服务器和基础环境 结语 1. 本文总结: 2. 后期优化: spring-boot项目的docker ...

  5. React 基于antd+video.js实现m3u8格式视频播放及实时切换

    文档连接地址(官网看起麻烦,看中文别人整理好的)https://blog.csdn.net/a0405221/article/details/80923090 React项目使用  安装依赖 npm ...

  6. log4net服务启动后没有记录日志

    有时候在用log4net的时候,调试或执行是ok的,但是安装服务后没有记录日志. 这是因为服务启动是在C盘启动,而程序放的位置在别的目录. 这时候需要指定读取配置文件的位置为程序所在的目录 strin ...

  7. 在vue项目中引入阿里图标库小记

    使用Vue技术栈开发不仅效率高,而且很友好,而且还有很多基于vue的UI框架,例如:element等,但是这类框架美中不足的是,图标太少.为了解决这个问题,不得不引入第三方字体库,今天以阿里图标库为例 ...

  8. FLV协议5分钟入门浅析

    FLV协议简介 FLV(Flash Video)是一种流媒体格式,因其体积小.协议相对简单,很快便流行开来,并得到广泛的支持. 常见的HTTP-FLV直播协议,就是使用HTTP流式传输通过FLV封装的 ...

  9. 从原理层面掌握@ModelAttribute的使用(核心原理篇)【一起学Spring MVC】

    每篇一句 我们应该做一个:胸中有蓝图,脚底有计划的人 前言 Spring MVC提供的基于注释的编程模型,极大的简化了web应用的开发,我们都是受益者.比如我们在@RestController标注的C ...

  10. Docker 方式部署 Solo 博客系统总结

      此篇为Docker部署方式,另有Tomcat部署方式,请参考文章<Tomcat 方式部署 Solo 博客系统总结>   最近搭建了一个博客系统,作为自己的主页,方便记录一些平时所见所闻 ...