hdu 2874 Connections between cities (并查集+LCA)
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
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.
Hint
Huge input, scanf recommended.
题意:
给出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)的更多相关文章
- 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] (lca->rmq)
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 ...
- HDU——2874 Connections between cities
Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- HDU 3371 Connect the Cities(并查集+Kruskal)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3371 思路: 这道题很明显是一道最小生成树的题目,有点意思的是,它事先已经让几个点联通了.正是因为它先 ...
- 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 LCA的模板题啦. #include <bits/stdc++.h> using namespace std; #defin ...
- HDU 2874 Connections between cities(LCA+并查集)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2874 [题目大意] 有n个村庄,m条路,不存在环,有q个询问,问两个村庄是否可达, 如果可达则输出 ...
- HDU 2874 Connections between cities (LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意是给你n个点,m条边(无向),q个询问.接下来m行,每行两个点一个边权,而且这个图不能有环路 ...
随机推荐
- 子域收集-fierce
fierce 是使用多种技术来扫描目标主机IP地址和主机名的一个DNS服务器枚举工具.运用递归的方式来工作.它的工作原理是先通过查询本地DNS服务器来查找目标DNS服务器,然后使用目标DNS服务器来查 ...
- QQ群认证 人数再度扩容 权限随之升级
群排名,得资源得天;之于排名,群容量有杠杆意义. 而今,流量分散,打法完全无法集中,全平台战略,越发凸显.QQ群,已是必争之地. 去年,Q群霸屏春天,一切那么顺其自然;而今,除了拼资源,还是拼资源.除 ...
- 使用webBrowser进行C#和JS通讯
.前台调用后台: 在webBrowser使用过程中为了C#和js通讯,webBrowser必须设置ObjectForScripting的属性,它是一个object,这个object可以提供给webBr ...
- PHP-提升PHP性能的几个扩展
下面介绍的几个扩展原理都是对OPCODE进行缓存(Opcode缓存原理查看http://www.cnblogs.com/JohnABC/p/4531029.html): Zend Opcache: 由 ...
- for循环小练习
for循环是前测试循环语句 for(初始值:判定条件:步长){ 循环语句 } For循环原理: For循环第一次执行:首先执行语句1,然后执行语句2,如果条件为真,向内执行执行循环语句3. 如果条件为 ...
- 爬虫之requests模块基础
一.request模块介绍 1. 什么是request模块 - python中原生的基于网络请求的模块,模拟浏览器发起请求. 2. 为什么使用request模块 - urllib需要手动处理url编码 ...
- POJ2553 汇点个数(强连通分量
The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 12070 Accepted: ...
- java 解析xml 多命名空间问题
先贴段有命名空间的xml吧.. <feed xmlns:im="http://itunes.apple.com/rss" xmlns="http://www.w3. ...
- spark优化系列一:参数介绍
1 spark on yarn常用属性介绍 属性名 默认值 属性说明 spark.yarn.am.memory 512m 在客户端模式(client mode)下,yarn应用master使用的内存数 ...
- Python正则反向引用
str2 ="2018-10-29"c =re.sub(r"(\d{4})-(\d{2})-(\d{2})","\g<1>/\g<2 ...