第一次按常规的方法求,将所有的查询的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. ERROR 临时

    ERROR ITMS-4238: "Redundant Binary Upload. There already exists a binary upload with build vers ...

  2. 提交bug的标准及书写规范

    Bug有效性 1.交付过程中测试者需按照专家设定好的模块,对Bug进行归类提交: 2.Bug的类型默认为UI问题.功能问题.崩溃问题,提交Bug时不能弄错: 3.需求是否明确.前提条件是否满足.输入数 ...

  3. python_0基础学习_day01

    Python是一门动态解释型的强类型定义语言 一.变量 变量命名规则 由数字.字母.下划线组成 不能以数字开头 要具有描述性 要区分大小写 禁止使用python的关键字(在pycharm中关键字明明变 ...

  4. Git 服务使用搭建集合

    Git 服务使用搭建集合 一.本地Git 仓库搭建与使用 1.Git 概念介绍 版本控制系统 版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统.大部分时候我们使用最频繁的还是对源 ...

  5. Linux部署项目遇到问题解决

    使用Linux部署web项目,可能会遇到各种各样问题导致服务启动失败,以下是我近期部署项目遇到的问题以及解决方案 一.场景:把war包放入tomcat的webapps文件夹下,然后启动tomcat服务 ...

  6. Java高级面试题解析(二):百度Java面试题前200页(精选)

    基本概念 操作系统中 heap 和 stack 的区别 heap是堆,stack是栈,是两种不同的数据结构.堆是队列优先,先进先出:栈是先进后出. 在java多线程中,每个线程都有自己的栈:不同的线程 ...

  7. coursera课程《how to learning 怎么学习》 总结

    总体来说,学完课程没有茅舍顿开的感觉,而是更加印证了之前的那个认知:大道至简,践则无敌,很多的学习方法上学的时候老师都教过我们,关键是我们能否坚持执行.课程讲了很多脑科学有关学习的知识,但对于我们实践 ...

  8. iview自定义实现多级表头

    最近更新: 2018-07-19 注意:最新版iview已经提供多级表头功能 参考 原理:利用多个Table组件通过显示和隐藏thead和tbody来拼接表格(较粗暴) html <div st ...

  9. WebService1

    一.什么是WebService(来源百度百科) Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述. ...

  10. ASP.NET Core 框架本质学习

    本文作为学习过程中的一个记录. 学习文章地址: https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 一. ASP.N ...