HDU 2874 Connections between cities(LCA(离线、在线)求树上距离+森林)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874
题目大意:给出n个点,m条边,q个询问,每次询问(u,v)的最短距离,若(u,v)不连通即不在同一颗树上则输出“Not connected”。
解题思路:这题也是模板题,有所不同的是这次给出的是森林而不是一棵树,所以vis数组得稍作修改,标记vis数组的是当前树的编号。下面给出Tarjan和倍增法两种解法。
Tarjan(离线)写法,被MLE坑了,离线写法必须要用静态邻接表,因为虽然n不大,但是q很大,所以如果存储问题邻接表会超内存。
还有突然脑残把dis[x]+dis[y]-2*dis[lca(x,y)]写成dis[x]+dis[y]-dis[lca(x,y)]漏了个2看了半天!!!MDZZ!!!
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e4+;
const int M=1e6+; struct qnode{
int to,id,next;
}q[M*]; struct node{
int to,w,next;
}edge[N*]; int n,m,cnt,num,idx1,idx2;
int res[M],root[N],vis[N],dis[N],head1[N],head2[N]; void addedge(int u,int v,int w){
edge[idx1].to=v;
edge[idx1].w=w;
edge[idx1].next=head1[u];
head1[u]=idx1++;
} void addq(int u,int v,int id){
q[idx2].to=v;
q[idx2].id=id;
q[idx2].next=head2[u];
head2[u]=idx2++;
} int find(int x){
return root[x]==x?x:root[x]=find(root[x]);
} void init(){
cnt=num=;
idx1=idx2=;
for(int i=;i<=n;i++) root[i]=i;
memset(res,-,sizeof(res));
memset(vis,,sizeof(vis));
memset(dis,,sizeof(dis));
memset(head1,,sizeof(head1));
memset(head2,,sizeof(head2));
} void lca(int u,int num){
//注意这里vis[u]标记的是树的编号,为了判断点是否在同一颗树上
vis[u]=num;
//root[u]=u;
for(int i=head1[u];i;i=edge[i].next){
node t=edge[i];
if(!vis[t.to]){
dis[t.to]=dis[u]+t.w;
lca(t.to,num);
root[t.to]=u;
}
}
for(int i=head2[u];i;i=q[i].next){
qnode t=q[i];
//属于同一颗树
if(vis[t.to]==num)
res[t.id]=dis[t.to]+dis[u]-*dis[find(t.to)];
}
} int main(){
int t;
while(~scanf("%d%d%d",&n,&m,&t)){
init();
for(int i=;i<=m;i++){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
addedge(a,b,w);
addedge(b,a,w);
}
for(int i=;i<=t;i++){
int a,b;
scanf("%d%d",&a,&b);
addq(a,b,i);
addq(b,a,i);
}
//森林
for(int i=;i<=n;i++){
if(!vis[i]) lca(i,i);
}
for(int i=;i<=t;i++){
if(res[i]==-)
puts("Not connected");
else
printf("%d\n",res[i]);
}
}
return ;
}
倍增法(在线)写法,这个倒是不卡vector了,解决了上面所有问题后,我又脑残了的,我TM忘记调用bz()函数了!!!干瞪着瞪了两个小时两个小时啊!!!
所以这道水题弄了我一个下午。。。。噗!
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e5+; struct node{
int to,w;
node(int to,int w):to(to),w(w){}
}; int n,m,q;
int fa[N][],depth[N],vis[N],dis[N];
vector<node>v[N]; void init(){
for(int i=;i<=n;i++) v[i].clear();
memset(vis,,sizeof(vis));
memset(depth,,sizeof(depth));
memset(dis,,sizeof(dis));
memset(fa,,sizeof(fa));
} void dfs(int u,int num){
vis[u]=num;
for(int i=;i<v[u].size();i++){
node t=v[u][i];
if(!vis[t.to]){
depth[t.to]=depth[u]+;
fa[t.to][]=u;
dis[t.to]=dis[u]+t.w;
dfs(t.to,num);
}
}
} //倍增,处理fa数组
void bz(){
for(int j=;j<=;j++){
for(int i=;i<=n;i++){
fa[i][j]=fa[fa[i][j-]][j-];
}
}
} int lca(int x,int y){
//保证深度大的点为x
if(depth[x]<depth[y])
swap(x,y);
int dc=depth[x]-depth[y];
for(int i=;i<;i++){
if(<<i&dc) //一个判断,模拟下就会清楚
x=fa[x][i];
}
if(x==y) return x; //如果深度一样,两个点相同,直接返回
for(int i=;i>=;i--){
if(fa[x][i]!=fa[y][i]){ //跳2^i不一样,就跳,否则不跳
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][];
} int main(){
while(~scanf("%d%d%d",&n,&m,&q)){
init(); //初始化
for(int i=;i<=m;i++){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
v[a].push_back(node(b,w));
v[b].push_back(node(a,w));
}
for(int i=;i<=n;i++){
if(!vis[i]) dfs(i,i);
}
bz(); //一定别忘了啊!!!
for(int i=;i<=q;i++){
int x,y;
scanf("%d%d",&x,&y);
if(vis[x]!=vis[y])
puts("Not connected");
else
printf("%d\n",dis[x]+dis[y]-*dis[lca(x,y)]);
}
}
return ;
}
HDU 2874 Connections between cities(LCA(离线、在线)求树上距离+森林)的更多相关文章
- hdu 2874 Connections between cities [LCA] (lca->rmq)
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- HDU 2874 Connections between cities(LCA Tarjan)
Connections between cities [题目链接]Connections between cities [题目类型]LCA Tarjan &题意: 输入一个森林,总节点不超过N ...
- HDU 2874 Connections between cities (LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意是给你n个点,m条边(无向),q个询问.接下来m行,每行两个点一个边权,而且这个图不能有环路 ...
- HDU 2874 Connections between cities(LCA)
题目链接 Connections between cities LCA的模板题啦. #include <bits/stdc++.h> using namespace std; #defin ...
- hdu 2874 Connections between cities (并查集+LCA)
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- hdu 2874 Connections between cities 带权lca判是否联通
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- hdu 2874 Connections between cities(st&rmq LCA)
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- HDU——2874 Connections between cities
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- Hdu 2874 Connections between cities
题意: 城市 道路 没有环 不一定连通的树 求两城市的最短距离 设想一下就是很多小树 那好办 思路: lca离线算法 然后有个技巧就是 每次我们tarjan一棵树不是最后树的节点都访问过并且孩子全 ...
随机推荐
- bzoj : 4504: K个串 区间修改主席树
4504: K个串 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 268 Solved: 110[Submit][Status][Discuss] ...
- 【转】基于R语言构建的电影评分预测模型
一,前提准备 1.R语言包:ggplot2包(绘图),recommenderlab包,reshape包(数据处理) 2.获取数据:大家可以在明尼苏达州大学的社会化计算研 ...
- day3 程序流程控制
今天主要学习了while和do/while,以及运用循环做一些小的练习. 学习了如何断点调试程序. 程序设计的步骤: 1.分析问题 2.确定数据结构和算法 3.编制程序 4.调试问题
- 科学计算三维可视化---Traits介绍
简介 Traits是开源扩展库,Traits本身与科学计算可视化没有直接关联,但他其实TVTK,Mayavi,TraitsUI基础 安装: pip3 install traits--cp36-cp36 ...
- bzoj千题计划152:bzoj3405: [Usaco2009 Open]Grazing2 移动牛棚
http://www.lydsy.com/JudgeOnline/problem.php?id=3405 n个牛棚,n-1段 因为要求距离尽量大,而且尽可能多的为d 所以: 第1个牛棚一定在位置1 最 ...
- 2016/1/2 Python中的多线程(1):线程初探
---恢复内容开始--- 新年第一篇,继续Python. 先来简单介绍线程和进程. 计算机刚开始发展的时候,程序都是从头到尾独占式地使用所有的内存和硬件资源,每个计算机只能同时跑一个程序.后来引进了一 ...
- Angular5基本入门
基本环境安装 首先,确定安装了nodejs与npm,angular 5要求node版本在6.9.x以上.npm版本在 3.x.x以上: 1.安装@angular/cli npm install -g ...
- Sparse AutoEncoder简介
1. AutoEncoder AutoEncoder是一种特殊的三层神经网络, 其输出等于输入:\(y^{(i)}=x^{(i)}\), 如下图所示: 亦即AutoEncoder想学到的函数为\(f_ ...
- 用代码从文件中导入数据到SQL Server
引言 导入数据到SQL Server 是常见的需求,特别是定期导入这种需求. 对于定期导入主要有以下几种方式可选择: Bulk Insert Bcp Utility OpenRowSet 写程序导入( ...
- exec操作文件描述符
exec命令可以用来替代当前shell:换句话说,并没有启动子shell.使用这一命令时任何环境都将被清除,并重新启动一个shell. 它的一半形式为: exec command 其中,command ...