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. frame3.5安装出错

    一般是因为禁用了microsoft update,可以在服务里禁用改为手动,之后启动,然后就可以安装

  2. bootstrap-daterangepicker插件运用

    引入:daterangepicker.css.daterangepicker.js.moment.js.moment.min.js 链接:https://files.cnblogs.com/files ...

  3. 解决 Android sdk content loader 0%

    第一次遇到这种情况,真的很头痛,没办法 ,是问题就要解决,在网上找了一些方法,归纳了下来. 方法一(关闭后重启): 遇到Eclipse右下角一直显示“Android sdk content loade ...

  4. 为什么我用了$().height()还是对不齐呢?

    有一个这样的需求:有两个显示内容的框,要使他们高度一致,因为他们存放的内容多少和结构不一样,左边内容少,右边内容多.这就导致了右边会比左边高,解决方法就是超出部分用滚轮显示,那这时就先要调整右边的高度 ...

  5. JDK8 新特性

    JDK8 新特性目录导航: Lambda 表达式 函数式接口 方法引用.构造器引用和数组引用 接口支持默认方法和静态方法 Stream API 增强类型推断 新的日期时间 API Optional 类 ...

  6. jquer搜索

    <body> <br/> <center> <tr><td>创建时间:</td><td><input type ...

  7. 让UltraEdit-32成为Delphi 7编译器的工具设置

    UltraEdit-32编译Delphi的工具设置 {================================================}Dcc32 命令行(&C):C:\Pro ...

  8. elasticsearch 5.x 系列之四(索引模板的使用,详细得不要不要的)

    1,首先看一下下面这个索引模板 curl -XPUT "master:9200/_template/template_1?pretty" -H 'Content-Type: app ...

  9. ip4addr_ntoa和不可重入函数

    在网络中,有一个转换IP地址到ASIIC字符串的函数,该函数的返回值所指向的ASIIC字符串驻留在静态内存中,所以该函数不可重入. 通俗的讲,在多任务系统中,一个任务执行在调用运行这个函数的时候,其他 ...

  10. Memcached Hash算法

    本文来自网易云社区 作者:吕宗胜 Hash算法 1. Memcached Hash介绍 我们在前面的文章中已经介绍过了Memcached的内存管理方式,LRU的策略.由于Memcached的数据存储方 ...