Connections between cities

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4057    Accepted Submission(s): 1178

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
Hint

Hint

Huge input, scanf recommended.

 
Source
 
Recommend
gaojie   |   We have carefully selected several similar problems for you:  2873 2876 2872 2875 2877 
 

题意:

给出n个点m条边的的森林,求两个点间的最短距离。

并查集+LCA:

这题想了挺久的,觉得是比较经典的题目。首先要知道这是一个森林,和一般的LCA不同,要变成LCA来写其实也不难(没想方法,最后看别人思路才恍然大悟),就是在所有树的根节点连上一个虚拟根节点0,将森林变成树,然后之前的节点用并查集处理,用于判断是否处于同棵树,处于同一个树再用LCA解决距离问题。

在线算法:

 //2328MS    3728K    2757 B    G++
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 20005
struct node{
int u,v,d;
int next;
}edge[*N];
int num,n,head[N];
int root[*N],rank[N];
int dep[*N],dis[N];
int dp[*N][],vis[N];
int set[N];
void addedge(int u,int v,int d)
{
edge[num].u=u;
edge[num].v=v;
edge[num].d=d;
edge[num].next=head[u];
head[u]=num++;
}
int Min(int a,int b)
{
return dep[a]<dep[b]?a:b;
}
int find(int x)
{
if(set[x]!=x)
set[x]=find(set[x]);
return set[x];
}
void merge(int a,int b)
{
int x=find(a);
int y=find(b);
if(x>y) set[x]=y;
else set[y]=x;
}
void dfs(int u,int deep)
{
vis[u]=;
root[++num]=u;
rank[u]=num;
dep[num]=deep;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v,d=edge[i].d;
if(vis[v]) continue;
dis[v]=dis[u]+d;
dfs(v,deep+);
root[++num]=u;
dep[num]=deep;
}
}
void init()
{
int nn=*n-;
int m=(int)(log(nn*1.0)/log(2.0));
for(int i=;i<=nn;i++)
dp[i][]=i;
for(int j=;j<=m;j++)
for(int i=;i+(<<j)-<=nn;i++)
dp[i][j]=Min(dp[i][j-],dp[i+(<<(j-))][j-]);
}
int RMQ(int l,int r)
{
int m=(int)(log((r-l+)*1.0)/log(2.0));
return Min(dp[l][m],dp[r-(<<m)+][m]);
}
int LCA(int u,int v)
{
int a=rank[u];
int b=rank[v];
if(a>b) return root[RMQ(b,a)];
else return root[RMQ(a,b)];
}
int main(void)
{
int m,c,u,v,d;
int in[N];
while(scanf("%d%d%d",&n,&m,&c)!=EOF)
{
memset(edge,,sizeof(edge));
memset(vis,,sizeof(vis));
memset(head,-,sizeof(head));
memset(in,,sizeof(in));
for(int i=;i<=n;i++) set[i]=i;
num=;
for(int i=;i<m;i++){
scanf("%d%d%d",&u,&v,&d);
addedge(u,v,d);
addedge(v,u,d);
in[v]++;
merge(u,v);
}
for(int i=;i<=n;i++) //连接森林的所有树
if(in[i]==){
addedge(,i,);
addedge(i,,);
}
num=;
dis[]=;
dfs(,);
init();
//for(int i=1;i<=2*n-1;i++) printf(i==2*n-1?"%d\n":"%d ",root[i]);
//for(int i=1;i<=2*n-1;i++) printf(i==2*n-1?"%d\n":"%d ",dep[i]);
//for(int i=1;i<=2*n-1;i++) printf(i==2*n-1?"%d\n":"%d ",dis[i]);
//for(int i=1;i<=2*n-1;i++) printf(i==2*n-1?"%d\n":"%d ",rank[i]);
while(c--){
scanf("%d%d",&u,&v);
//printf("*%d %d\n",find(u),find(v));
if(find(u)!=find(v)) puts("Not connected");
else printf("%d\n",dis[u]+dis[v]-*dis[LCA(u,v)]);
}
}
return ;
}

Tarjan离线做法:

 //2359MS     30504K    1830B     G++
#include<iostream>
#include<queue>
#include<vector>
#define N 10005
using namespace std;
struct node{
int v,d;
node(int a,int b){
v=a;d=b;
}
};
vector<node>child[N],V[N];
int fa[N],vis[N],dis[N],mark[N];
int res[*N];
int n;
int find(int x)
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
void Tarjan(int u)
{
fa[u]=u;
vis[u]=;
for(int i=;i<V[u].size();i++){
int v=V[u][i].v,d=V[u][i].d;
if(vis[v] && res[d]==- && !mark[find(v)])
res[d]=dis[u]+dis[v]-*dis[find(v)];
}
for(int i=;i<child[u].size();i++){
int v=child[u][i].v,d=child[u][i].d;
if(vis[v]) continue;
dis[v]=dis[u]+d;
Tarjan(v);
fa[v]=u;
}
}
int main(void)
{
int m,c;
int u,v,d;
while(scanf("%d%d%d",&n,&m,&c)!=EOF)
{
for(int i=;i<=n;i++){
child[i].clear();
V[i].clear();
fa[i]=i;
vis[i]=mark[i]=;
}
memset(res,-,sizeof(res));
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&d);
child[u].push_back(node(v,d));
child[v].push_back(node(u,d));
}
for(int i=;i<=c;i++){
scanf("%d%d",&u,&v);
V[u].push_back(node(v,i));
V[v].push_back(node(u,i));
}
for(int i=;i<=n;i++){
if(!vis[i]){
dis[i]=;
Tarjan(i);
mark[i]=;
}
}
//for(int i=1;i<=n;i++) printf(i==n?"%d\n":"%d ",dis[i]);
//for(int i=1;i<=n;i++) printf(i==n?"%d\n":"%d ",fa[i]);
for(int i=;i<=c;i++){
if(res[i]==-) puts("Not connected");
else printf("%d\n",res[i]);
}
}
}

hdu 2874 Connections between cities (并查集+LCA)的更多相关文章

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

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

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

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

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

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

  4. HDU——2874 Connections between cities

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

  5. HDU 3371 Connect the Cities(并查集+Kruskal)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3371 思路: 这道题很明显是一道最小生成树的题目,有点意思的是,它事先已经让几个点联通了.正是因为它先 ...

  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 LCA的模板题啦. #include <bits/stdc++.h> using namespace std; #defin ...

  8. HDU 2874 Connections between cities(LCA+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2874 [题目大意] 有n个村庄,m条路,不存在环,有q个询问,问两个村庄是否可达, 如果可达则输出 ...

  9. HDU 2874 Connections between cities (LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意是给你n个点,m条边(无向),q个询问.接下来m行,每行两个点一个边权,而且这个图不能有环路 ...

随机推荐

  1. C# register global hotkey ,onekey 注册多个全局热键以及单个全局热键

    我们需要用非Hook的方法,来给我们的app 或者winform注册热键. 就像下面的 , 欧陆词典注册的一个热键F6一样, 在winform最小化的情况下,也能够全局响应热键. 这里使用系统API来 ...

  2. 吐血分享:QQ群霸屏技术教程(接单篇)

    在文章<QQ群霸屏技术教程(利润篇)>中,阿力推推提及到QQ群霸屏技术变现的方式,稍显粗略,这里详尽介绍下(老鸟漂过). 资本 资本之上,才谈得上接单,没技能,接个毛线. 1擅长点. 建议 ...

  3. doc命令操作数据库(下)

    1.给数据表添加一组数据: 2.给数据表添加多组数据: 3.对数据进行删除和修改: 4.用select查询单个或多个数据信息: 5.去除重复值: 6.查询的各种用法: between的用法: 查询排序 ...

  4. Thinkphp5所有页面验证用户是否登陆

    新建Base.php控制器,所有的页面继承自它 <?php namespace app\index\controller; use think\Controller; class Base ex ...

  5. linux几条基本命令和解释

    pwd 查看当前目录/     根目录ls    查看当前目录所包含文件ls -l    查看当前目录所包含文件的详细信息d rwx rwx r-x 1 root root1  2     3   4 ...

  6. Kubernetes-深入分析集群安全机制

    Kubernetes过一系列机制来实现集群的安全机制,包括API Server的认证授权.准入控制机制及保护敏感信息的Secret机制等.集群的安全性必须考虑以下的几个目标: 保证容器与其所在宿主机的 ...

  7. css在线sprite

    大家知道网站图片多,浏览器下载多个图片要有多个请求.可是请求比较耗时,那怎么办呢? 对,方法就是css sprite. 今天我们来看看css在线sprite 百度搜索css-sprite 打开www. ...

  8. WPF ItemsControl 手动刷新

    原文:WPF ItemsControl 手动刷新 遇到这样一个问题, 我的ItemsSource是绑定到一个ObservableCollection<T>类型的实力上去的. 但是T类型没有 ...

  9. BLE(Bluetooth Low Energy)---first part

    原文地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#terms (本人是技术宅,翻译时候,只要 ...

  10. 13 ThreadLocal

    ThreadLocal 在多线程环境下,每个线程都有自己的数据.一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁. 1. 使用函数 ...