[HDU2874]Connections between cities
思路:
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的更多相关文章
- hdu-2874 Connections between cities(lca+tarjan+并查集)
题目链接: Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/327 ...
- [hdu2874]Connections between cities(LCA+并查集)
题意:n棵树,求任意两点的最短距离. 解题关键:并查集判断两点是否位于一棵树上,然后求最短距离即可.此题可以直接对全部区间直接进行st表,因为first数组会将连接的两点的区间表示出来. //#pra ...
- HDU2874 Connections between cities 最近公共祖先
第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先.因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟 ...
- hdu 2874 Connections between cities [LCA] (lca->rmq)
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- Connections between cities
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...
- HDU 2874 Connections between cities(LCA Tarjan)
Connections between cities [题目链接]Connections between cities [题目类型]LCA Tarjan &题意: 输入一个森林,总节点不超过N ...
- 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 (并查集+LCA)
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
随机推荐
- SQL记录-PLSQL-DBMS输出
PL/SQL DBMS输出 DBMS_OUTPUT是一个内置的软件包,能够显示输出显示调试信息,并从PL/ SQL块,子程序,包和触发器发送消息.我们已经使用这个包在我们所有的教程中. 让我们来看 ...
- MingW-v4.8.0+EDE-v13.04 配置使用C语言图形库
From: http://www.cnblogs.com/killerlegend/p/3946768.html Author:KillerLegend Date:2014.8.30 MingW的配置 ...
- SQL语句(八)按条件查询
SELECT * FROM student SELECT sclass, snumb, sname FROM student --物理班有哪些同学 --年龄小于20岁的有哪些同学? --定价在30元以 ...
- 如何将U盘转化成NTFS格式
拷贝数据到U盘,出现 出现错误0x80070052:无法创建目录或文件 然后发现应该是U盘为fat32格式的,感觉应该是这个问题 方法一:如果你是新买的U盘,或者U盘内数据已经备份到电脑,可以使用该条 ...
- git 学习小记之图形化界面客户端
习惯了 Windows 的用户,一直不喜欢用类似命令行的东西来操作,当然我也不是不喜欢,只是操作太慢了.也许 Linux 大神在命令行的帮助下,办事效率翻倍,那也是非常常见的事情..当然我不是大神,所 ...
- 【51Nod】1920 空间统计学 状压DP
[题目]1920 空间统计学 [题意]给定m维空间中的n个点坐标,满足每一维坐标大小都在[0,3]之间,现在对于[0,3*m]的每个数字x统计曼哈顿距离为x的有序点对数.\(n \leq 2*10^5 ...
- iOS手势UIGestureRecognizer的使用及手势冲突的解决办法【转】
转自:iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用 关于手势的一篇很好的帖子,转载过来免得丢失.你可能最感兴趣的是手势间的互斥处理,那么就搜索 4.手势间的互斥处 ...
- list(列表)操作【五】
L表示从左边(头部)开始插与弹出,R表示从右边(尾部)开始插与弹出. 一.概述: 在Redis中,List类型是按照插入顺序排序的字符串链表.和数据结构中的普通链表一样,我们可以在其头部(l ...
- Windows命令-系统木马取样
1.前言 工作中偶尔会遇到去现场提取木马样本回公司分析的情况.如果是生产环境下,不方便安装各类抓包.安全软件时.能用系统自带的命令去定位出木马程序相关的信息是最理想不过的状态. 2.Windows常用 ...
- Qt 程序等待多长时间执行Sleep
#include <QTime> void MainWindow::Sleep(unsigned int msec) { QTime reachTime=QTime::currentTim ...