第一次按常规的方法求,将所有的查询的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. 用scrapy爬取搜狗Lofter图片

    用scrapy爬取搜狗Lofter图片 # -*- coding: utf-8 -*- import json import scrapy from scrapy.http import Reques ...

  2. MRCPv2在电信智能语音识别业务中的应用

    1. MRCPv2协议简介 媒体资源控制协议(Media Resource Control Protocol, MRCP)是一种基于TCP/IP的通讯协议,用于客户端向媒体资源服务器请求提供各种媒体资 ...

  3. 解决报错:类型“System.Object”在未被引用的程序集中定义。必须添加对程序集“System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”的引用

    Razor视图引擎中,使用部分视图编译报错 类型“System.Object”在未被引用的程序集中定义.必须添加对程序集“System.Runtime, Version=4.0.0.0, Cultur ...

  4. Unity经典游戏教程之:合金弹头

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

  5. Docker笔记(七):常用服务安装——Nginx、MySql、Redis

    开发中经常需要安装一些常用的服务软件,如Nginx.MySql.Redis等,如果按照普通的安装方法,一般都相对比较繁琐 —— 要经过下载软件或源码包,编译安装,配置,启动等步骤,使用 Docker ...

  6. Spring 常犯的十大错误,答应我 打死都不要犯好吗?

    1. 错误一:太过关注底层 我们正在解决这个常见错误,是因为 “非我所创” 综合症在软件开发领域很是常见.症状包括经常重写一些常见的代码,很多开发人员都有这种症状. 虽然理解特定库的内部结构及其实现, ...

  7. 使用sublime调试node.js

    安装node相关 从node官网下载node的安装文件,我下的版本是node-v0.10.22-x64.exe,安装完node,node相关工具应该都加都环境变量path中了. 命令行下安装node- ...

  8. Flink 源码解析 —— 深度解析 Flink 是如何管理好内存的?

    前言 如今,许多用于分析大型数据集的开源系统都是用 Java 或者是基于 JVM 的编程语言实现的.最着名的例子是 Apache Hadoop,还有较新的框架,如 Apache Spark.Apach ...

  9. cookie session sessionStorage localStorage

    什么是会话? 会话指的是浏览器与服务器之间的数据交互.所白了就是 浏览器和服务器进行的请求和响应. http协议是无状态的,多次请求之间没有关联性 cookie和session的作用?干啥的? 利用c ...

  10. Oracle Job定时任务详解、跨数据库数据同步

    业务需求,需要与A公司做数据对接,我们公司用的Oracle,A公司用的SQL Server数据库,如何跨数据库建立连接呢?这里使用的是DBLink,不会配置的请看我的另外一篇博客:https://ww ...