hdu 2874 Connections between cities [LCA] (lca->rmq)
Connections between cities
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4425 Accepted Submission(s): 1263
Problem Description
After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city. For most of roads had been totally destroyed during the war, there might be no path between two cities, no circle exists as well.
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.
Input
Input consists of multiple problem instances.For each instance, first line contains three integers n, m and c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n represents the number of cities numbered from 1 to n. Following m lines, each line has three integers i, j and k, represent a road between city i and city j, with length k. Last c lines, two integers i, j each line, indicates a query of city i and city j.
Output
For each problem instance, one line for each query. If no path between two cities, output “Not connected”, otherwise output the length of the shortest path between them.
Sample Input
5 3 2
1 3 2
2 4 3
5 2 3
1 4
4 5
Sample Output
Not connected
6
题意:给你n给点,m条边,有c次询问,每次询问u,v两个点,你需要判断u,v是否连通,u,v的最短距离是多少。
::对于是否连通直接用并查集就可以了,对于连通的两个点最短距离怎么求呢。
数据很大,不允许每次询问都跑一次最短路的算法,那么就考虑一下一劳永逸的办法,有没有办法经过预处理,每次询问都能快速给出答案。
注意到这是无环图,可以转化成树的做法。
对于单个连通分量随意取一点,令其为根,进行dfs遍历,得到每个点到根结点的距离,保存起来(我这里用dis保存),并且得到一个dfs遍历的序列,求出每两个点的lca。如何求lca具体看
lca –> rmq. 那么对于询问在同一个连通分量的两个的距离dis(u->v) = dis(u)+dis(v)-2*dis(lca(u,v));//u到根结点的距离+v到根结点的距离-(u,v)最早公共祖先到根结点的距离的2倍
LCA转RMQ
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = ;
int n, m, Q, fa[N], dis[N];
int id[N], fid[N], gid;
int pos, R[N], E[N<<], d[N<<][];
bool vis[N]; struct edge {
int u, v, w, next;
edge() {}
edge(int u, int v, int w, int next):u(u),v(v),w(w),next(next) {}
}e[N<<];
int ecnt, head[N]; inline void add(int u, int v, int w) {
e[ecnt] = edge(u, v, w, head[u]);
head[u] = ecnt++;
} int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
} void dfs(int u, int dep){
id[u] = ++gid;
fid[gid] = u;
R[u] = ++pos;
E[pos] = id[u]; //保存dfs序列,求RMQ(lca) dis[u] = dep; // 结点u到根结点的距离
vis[u] = ;
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(vis[v]) continue;
dfs(v, dep + e[i].w);
E[++pos] = id[u];
}
} void init_RMQ() {
for(int i = ; i <= pos; ++i) d[i][] = E[i];
for(int j = ; (<<j) <= pos; ++j) {
for(int i = ; i + (<<j) - <= pos; ++i) {
d[i][j] = min(d[i][j-], d[i + (<<(j-))][j-]);
}
}
} inline int RMQ(int L, int R) {
if(L>R) swap(L, R);
int k = ;
while(<<(k + ) <= R - L + ) ++k;
return min(d[L][k], d[R-(<<k)+][k]);
} void solve(){
ecnt = ; gid = , pos = ;
for(int i = ; i <= n; ++i) {
head[i] = -;
fa[i] = i;
} int u, v, w;
for(int i = ; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
u = find(u), v = find(v);
fa[u] = v;
} memset(vis, , sizeof(vis));
for(int i = ; i <= n; ++i) {
if(!vis[i]) dfs(i, ); //对于每个连通块取一个根结点
}
init_RMQ(); int lca, ans;
while(Q--){
scanf("%d%d", &u, &v);
if(find(u) != find(v)) {
puts("Not connected");
}
else {
lca = fid[ RMQ(R[u], R[v]) ];
ans = dis[u] + dis[v] - *dis[lca];
printf("%d\n", ans);
}
}
} int main()
{
// freopen("in.txt", "r", stdin);
while(scanf("%d%d%d", &n, &m, &Q)>) solve();
return ;
}
tarjan离线算法


view code#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1e4+10;
const int maxc=1e6+10;
struct node{
int to,w;
node(int a=0,int b=0){to=a;w=b;}
};
int f[maxn],dis[maxn],n,ans[maxc],vis[maxn],mark[maxn];
//f[i]并查集所用,记录前继结点
//dis[i]记录个点到跟结点的距离
//ans记录m个询问的答案
//vis标记查询过了的点
//mark记录已访问过的根节点。由于已遍历的树所有结点的find都是根节点,这样就能判断下是否在别的树里了
vector<node>e[maxn];//记录树
vector<node>q[maxn];//记录所求最短距离的两点
int find(int x)
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
void lca(int u)
{
int i,j,k,v,c;
for(j=0;j<q[u].size();j++)
{
c=q[u][j].to;
//如果所求两点中的对应点已知,则必定在同一子树上,由于并查集只记录所在子树。所以find(c),就是最近公共祖先
if(vis[c]&&ans[q[u][j].w]==-1&&mark[find(c)]!=1)
{
//cout<<f[c]<<"***"<<endl;
ans[q[u][j].w]=dis[u]+dis[c]-2*dis[find(c)];
}
}
for(i=0;i<e[u].size();i++)
{
v=e[u][i].to;
if(vis[v])continue;
vis[v]=1;
dis[v]=dis[u]+e[u][i].w;
lca(v);//深度优先搜索
f[v]=u; }
}
int main()
{
int n,m,c;
while(scanf("%d%d%d",&n,&m,&c)!=EOF)
{
int i,j,k,x,y,z;
for(i=1;i<=n;i++)
{
e[i].clear();
q[i].clear();
f[i]=i;
vis[i]=mark[i]=0;
}
memset(ans,-1,sizeof(ans));
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
e[x].push_back(node(y,z));
e[y].push_back(node(x,z));
}
for(i=1;i<=c;i++)
{
scanf("%d%d",&x,&y);
// if(x==y){ans[i]=0;continue;}
q[x].push_back(node(y,i));
q[y].push_back(node(x,i));
}
for(i=1;i<=n;i++)
{
if(!vis[i])
{
vis[i]=1;
dis[i]=0;
lca(i);
mark[i]=1;
}
}
for(i=1;i<=c;i++)
{
if(ans[i]!=-1)
printf("%d\n",ans[i]);
else
printf("Not connected\n");
}
}
return 0;
}
/*
最近公共祖先lca 离线算法/Tarjan算法,用mark标记是否在同一组里。 方法举例说明:
1
/ \
2 3
/ \
4 5
/ /
7 8
/
9
查询(4,9):到4时,由于vis[9]=0,所以继续;到9后,最近公共祖先就是f[4]=4(回溯的时候记录父节点);
查询(9,8):深度优先搜索,所以到8时才询问;要到8必须回溯到2,在进到8这个子树,所以以记录f[9]=7;f[7]=4;f[4]=2;f[2]=2;所以find(2)=2;
查询(8,3):跟上条相似,必须回溯1才能到3,而find(8)=1就是最近公共祖先;
我们可以发现,对于查询的两点,都要在先查询到的点开始,回溯到最近公共祖先,才查询相对应的点。这也就是离线算法的思路了。。
hdu 2874 Connections between cities [LCA] (lca->rmq)的更多相关文章
- 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 LCA的模板题啦. #include <bits/stdc++.h> using namespace std; #defin ...
- HDU 2874 Connections between cities(LCA离线算法实现)
http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 求两个城市之间的距离. 思路: LCA题,注意原图可能不连通. 如果不了解离线算法的话,可以看我之 ...
- HDU 2874 Connections between cities(LCA(离线、在线)求树上距离+森林)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 题目大意:给出n个点,m条边,q个询问,每次询问(u,v)的最短距离,若(u,v)不连通即不在同 ...
- HDU 2874 Connections between cities(LCA+并查集)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2874 [题目大意] 有n个村庄,m条路,不存在环,有q个询问,问两个村庄是否可达, 如果可达则输出 ...
- 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 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
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
随机推荐
- PHP的加密解密字符串函数
程序中经常使用的PHP加密解密字符串函数 代码如下: /********************************************************************* 函数 ...
- 第一个Object-C类
转自:http://www.cnblogs.com/heyonggang/p/3441051.html 来源:http://www.cnblogs.com/mjios/archive/2013/04/ ...
- 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar
[源码下载] 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar 作者:webabcd 介绍重新想象 Windows 8.1 Sto ...
- SqlServer根据时段统计数据
create table ST_PPTN_R_Real ( TID int primary key identity(1,1), STCD varchar(100) not null, TM date ...
- ComponentOne Studio for Enterprise 2015 v1 全新发布
ComponentOne Studio 即将发布2015年的第一个版本.2015 v1版本聚焦于优化性能.提升数据可视化能力.加强数据管理以及更人性的输入方式及报表解决方案. 免费下载试用 WinFo ...
- JavaSE——TCP网络编程(二)
ServerSocket 类与Socket 类的不同用法: ServerSocket类: 创建一个ServerSocket类,同时在运行该语句的计算机的指定端口处建立一个监听服务,如: Serv ...
- ztree树 叶子节点路径的集合
1.Question Description: ztree树各个节点都带有路径,如“/根节点”,"/根节点/一级节点",“根节点/一级节点/二级节点‘; 现在想获取所选的最末级节点 ...
- PHP学习笔记:利用时间和mt_rand函数获取随机名字
这个知识会在文件上传等场合用到,还没学面向对象,现在用函数形式呈献给各位,代码都做了备注,有不懂得可以在线提问. <?php /** * Created by PhpStorm. * User: ...
- ES6中generator传参与返回值
先看两个例子, 1, function* f() { for(var i=0; true; i++) { var reset = yield i; if(reset) { i = -1; } } } ...
- RHEL7文件归档与压缩
本文介绍RHEL7.2文件的归档和压缩 文件归档 归档的好处:方便使用.查询.阅读,易于管理 (批量删除文件) 常用操作 命令:tar 作用:将许多文件一起保存至一个单独的磁带或磁盘归档,并能从归档中 ...