第一次按常规的方法求,将所有的查询的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. 实战SpringCloud响应式微服务系列教程(第二章)

    接上一篇:实战SpringCloud响应式微服务系列教程(第一章) 1.1.2背压 背压是响应式编程的核心概念,这一节也是我们了解响应式编程的重点. 1.背压的机制 在生产者/消费者模型中,我们意识到 ...

  2. 【JDK】JDK源码分析-HashMap(1)

    概述 HashMap 是 Java 开发中最常用的容器类之一,也是面试的常客.它其实就是前文「数据结构与算法笔记(二)」中「散列表」的实现,处理散列冲突用的是“链表法”,并且在 JDK 1.8 做了优 ...

  3. 【Android Studio】查看源码时提示“throw new RuntimeException("Stub!")”

    如题-- 详细问题及解决方法: http://blog.csdn.net/u010917495/article/details/51234179

  4. 蓝桥杯 2n皇后问题 深搜

    默认大家会了n皇后问题 基础练习 2n皇后问题   时间限制:1.0s   内存限制:512.0MB     问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和 ...

  5. dubbo文档笔记

    配置覆盖关系 以 timeout 为例,显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似: 方法级优先,接口级次之,全局配置再次之. 如果级别一样,则消费 ...

  6. spark shuffle写操作之SortShuffleWriter

    提出问题 1. spark shuffle的预聚合操作是如何做的,其中底层的数据结构是什么?在数据写入到内存中有预聚合,在读溢出文件合并到最终的文件时是否也有预聚合操作? 2. shuffle数据的排 ...

  7. Android 打包时 Keep 住某些方法或类

    # ${android_sdk}/tools/proguard/proguard-android.txt # Understand the @Keep support annotation. -kee ...

  8. android ——活动的生命周期

    在其生命周期内,activity在运行.暂停和停止三种可能的状态间进行转换,不同状态之间互相转换的时候的调用不同的方法,重写这些方法就能在活动切换,被销毁时保存或传输数据,在被启动.被切换出来时接收数 ...

  9. Python 学习笔记(6)— 字符串格式化

    字符串格式化处理 远古写法 以前通常使用运算符号 % ,%s 插入的值 String 类型,%.3f 指插入的值为包含 3 位小数的浮点数: format1 = "%s, %s!" ...

  10. AutoCAD .NET: 遍历模型空间

    原文:http://spiderinnet1.typepad.com/blog/2012/06/autocad-net-iterate-through-model-space.html https:/ ...