思路:
LCA裸题。本来是帮pechpo调错,结果自己写了半天…
设$dis_x$是点$x$到根结点距离,不难想到两点$u$、$v$之间最短距离等于$dis_u+dis_v-dis_{LCA(u,v)}\times 2$。
然后我们可以用Tarjan做,然后发现MLE了。
以为是这题卡vector的内存,于是改成了链式前向星,还是MLE。
后来发现题目的内存限制只有32M,算了算,如果将数据离线保存下来,大约有20000K左右,再加上函数里面的栈,似乎确实有点危险。
最后改成用ST做,只用了5852KB。

 #include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
inline int getint() {
char ch;
while(!isdigit(ch=getchar()));
int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
inline int flog2(const float x) {
return ((unsigned&)x>>&)-;
}
const int V=,logV=;
struct Edge {
int to,w,next;
};
Edge edge[V<<];
int e[V],esz;
inline void add_edge(const int u,const int v,const int w) {
esz++;
edge[esz]=(Edge){v,w,e[u]};
e[u]=esz;
}
bool vis[V];
int dis[V],dep[V];
int anc[V][logV];
inline void init() {
esz=;
memset(vis,,sizeof vis);
memset(dis,,sizeof dis);
memset(anc,,sizeof anc);
memset(dep,,sizeof dep);
memset(e,,sizeof e);
}
void dfs(const int x,const int par) {
vis[x]=true;
anc[x][]=par;
dep[x]=dep[par]+;
for(int i=e[x];i;i=edge[i].next) {
int &y=edge[i].to;
if(y==par) continue;
dis[y]=dis[x]+edge[i].w;
dfs(y,x);
}
}
int LCA(int a,int b) {
if(dep[a]<dep[b]) std::swap(a,b);
for(int i=flog2(dep[a]);i>=;i--) {
if(dep[a]-(<<i)>=dep[b]) a=anc[a][i];
}
if(a==b) return a;
for(int i=flog2(dep[a]);i>=;i--) {
if(anc[a][i]!=anc[b][i]) a=anc[a][i],b=anc[b][i];
}
return anc[a][];
}
int main() {
int n,m,q;
while(~scanf("%d%d%d",&n,&m,&q)) {
init();
while(m--) {
int u=getint(),v=getint(),w=getint();
add_edge(u,v,w);
add_edge(v,u,w);
}
for(int i=;i<=n;i++) {
if(!vis[i]) dfs(i,);
}
for(int j=;j<=flog2(n);j++) {
for(int i=;i<=n;i++) {
anc[i][j]=anc[anc[i][j-]][j-];
}
}
while(q--) {
int u=getint(),v=getint();
if(int lca=LCA(u,v)) {
printf("%d\n",dis[u]+dis[v]-dis[lca]*);
}
else {
puts("Not connected");
}
}
}
return ;
}

本来用Tarjan算法是MLE的,当时是用了三个数组$qx[Q]$,$qy[Q]$,$lca[Q]$,分别存储每一个$x$,$y$和$LCA(x,y)$,Tarjan的时候求出LCA。最后答案输出的时候计算距离。
后来考虑在Tarjan的同时直接将它们之间的距离求出来,这样一下子就节省了两个数组,最后跑了29376K,还是勉强卡过去。

 #include<cstdio>
#include<cctype>
#include<cstring>
inline int getint() {
char ch;
while(!isdigit(ch=getchar()));
int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int V=,E=,Q=;
struct Edge {
int to,w,next;
};
Edge edge[E<<];
int e[V],esz;
inline void add_edge(int u,int v,int w) {
esz++;
edge[esz]=(Edge){v,w,e[u]};
e[u]=esz;
}
struct Query {
int to,id,next;
};
Query query[Q<<];
int q[V],qsz;
inline void add_query(int u,int v,int id) {
qsz++;
query[qsz]=(Query){v,id,q[u]};
q[u]=qsz;
}
class DisjointSet {
private:
int anc[V];
public:
void reset() {
for(int i=;i<V;i++) anc[i]=i;
}
int Find(int x) {
return x==anc[x]?x:anc[x]=Find(anc[x]);
}
void Union(int x,int y) {
anc[Find(x)]=Find(y);
}
bool isConnected(int x,int y) {
return Find(x)==Find(y);
}
};
DisjointSet s;
int ans[Q];
int vis[V];
int dis[V]={};
int root;
void Tarjan(int x,int par) {
vis[x]=root;
for(int i=e[x];i;i=edge[i].next) {
int y=edge[i].to;
if(y!=par) {
dis[y]=dis[x]+edge[i].w;
Tarjan(y,x);
s.Union(y,x);
}
}
for(int i=q[x];i;i=query[i].next) {
int y=query[i].to;
if(vis[y]==root) {
ans[query[i].id]=dis[x]+dis[y]-dis[s.Find(y)]*;
}
}
}
inline void init() {
s.reset();
esz=qsz=;
for(int i=;i<Q;i++) ans[i]=-;
memset(vis,,sizeof vis);
memset(e,,sizeof e);
memset(q,,sizeof q);
}
int main() {
int n,m,q;
while(~scanf("%d%d%d",&n,&m,&q)) {
init();
while(m--) {
int u=getint(),v=getint(),w=getint();
add_edge(u,v,w);
add_edge(v,u,w);
}
for(int i=;i<q;i++) {
int u=getint(),v=getint();
add_query(u,v,i);
add_query(v,u,i);
}
for(int i=;i<=n;i++) {
if(!vis[i]) {
root=i;
Tarjan(i,);
}
}
for(int i=;i<q;i++) {
if(~ans[i]) {
printf("%d\n",ans[i]);
}
else {
puts("Not connected");
}
}
}
return ;
}

[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+并查集)

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

  3. HDU2874 Connections between cities 最近公共祖先

    第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先.因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟 ...

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

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

  5. Connections between cities

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

  6. HDU 2874 Connections between cities(LCA Tarjan)

    Connections between cities [题目链接]Connections between cities [题目类型]LCA Tarjan &题意: 输入一个森林,总节点不超过N ...

  7. hdu 2874 Connections between cities 带权lca判是否联通

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

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

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

  9. hdu 2874 Connections between cities (并查集+LCA)

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

随机推荐

  1. RestFul风格接口示例

    REST是英文representational state transfer(表象性状态转变)或者表述性状态转移;Rest是web服务的一种架构风格;使用HTTP,URI,XML,JSON,HTML等 ...

  2. Redis记录-redis和memcached的区别

    1.Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等: 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供lis ...

  3. python 玩具代码

    脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它,就这么简单 #!/usr/bin/python是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python ...

  4. Java入门系列(六)方法

    方法返回多个值 使用集合类 /** * 方法1:使用集合类 (Map以外的集合类也可以随意使用) * 目标:返回一个数组的最大值和最小值 */ public Map<String, Intege ...

  5. 20155314 2016-2017-2 《Java程序设计》第5周学习总结

    20155314 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 理解异常架构 牚握try...catch...finally处理异常的方法 会用throw, ...

  6. 第11月第8天 ffmpeg ffplay

    static int ffplay_video_thread(void *arg) { FFPlayer *ffp = arg; VideoState *is = ffp->is; AVFram ...

  7. python之pip安装mysql-python失败

    前言 由于公司使用的python版本是python2,并且连接mysql的包是mysql-python,但是mysql-python 使用pip安装报错,需要C++环境等依赖,于是使用wheel直接安 ...

  8. Windows修改默认远程端口号3389

    1.打开注册表:运行-regedit: 2.HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\Wds\Repwd\ ...

  9. 串口硬流控原理验证RTS与CTS

    物理连接(交叉连接) 主机的RTS(输出)信号,连接到从机的CTS(输入)信号. 主机的CTS(输入)信号,连接到从机的RTS(输出)信号. 主机发送过程: 主机查询主机的CTS脚信号,此信号连接到从 ...

  10. mac ssh 自动登陆设置

    1.首先找到.ssh目录 一般在用户名目录下. ls -a查看 如果没有就重新创建一个 chennan@bogon :mkdir .ssh chennan@bogon 查看当前的 bogon:.ssh ...