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 ...
随机推荐
- 重构第24天 分解复杂的判断(Remove Arrowhead Antipattern)
理解: 当你的代码中有很深的嵌套条件时,花括号就会在代码中形成一个长长的箭头.我们经常在不同的代码中看到这种情况,并且这种情况也会扰乱代码的可读性. 如下代码所示,HasAccess方法里面包含一些嵌 ...
- 收集数据至泛型Dictionary
开发时,我们经常使用到泛型,不管是List<T>,还是Dictionary<T,V>,下面Insus.NET在测试一些功能,当使用到一些临时数据集时,有好几种方法把数据收集至D ...
- ScriptManager和UpdatePanel控件实现局部刷新
ScriptManager和UpdatePanel控件联合使用可以实现页面异步局部更新的效果.其中的UpdatePanel就是设置页面中异步局部更新区域,它必须依赖于ScriptManager存在,因 ...
- easyui-简单用法寄一些属性
Easyui 总结 优点: A.简单易用 继承 jQuery 简易使用特性,提供高度抽象接口,短期改善网站易用性. B.开源免费 采用 MIT & GPL 双协议授权,轻松满足自由产品至企业产 ...
- C#中 导入和导出Excel的方法
using System.Data; using System.Data.OleDb; /// <summary> /// Excel转为DataTable /// </summar ...
- 205 Isomorphic Strings
Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...
- CentOS修改服务器系统时间
linux安装完毕后,一般都是国外的世界,一点都不方便设置任务,或者导致网站获取本地的时间错乱,所以就需要把服务器的时间改为和本地时间一致,也就是换成中国的时间. 第一条指令:date –s '201 ...
- Vue自带的过滤器
gitHub地址:https://github.com/lily1010/vue_learn/tree/master/lesson05 一 过滤器写法 {{ message | Filter}} 二 ...
- 新著作计划:《水利水电工程施工导流 水力计算与.NET编程》
目 录 第一篇 基础理论篇 第1章 施工导截流设计概述 第2章 基本水力计算 2.1 临界水深计算 2.2 正常水深计算 2.3 堰流水力计算 2.4 明渠流水力计算 2.5 管流水力计算 第3章 ...
- Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
from:http://blog.tallan.com/2012/07/18/creating-a-sharepoint-bcs-net-assembly-connector-to-crawl-rss ...