HDU-2874 Connections between cities(倍增法)

Connectionsbetween cities

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

Problem Description

After World War X, a lot ofcities have been seriously damaged, and we need to rebuild those cities.However, some materials needed can only be produced in certain places. So weneed to transport these materials from city to city. For most of roads had beentotally destroyed during the war, there might be no path between two cities, nocircle exists as well.
Now, your task comes. After giving you the condition of the roads, we want toknow if there exists a path between any two cities. If the answer is yes,output the shortest path between them.

 

 

Input

Input consists of multipleproblem instances.For each instance, first line contains three integers n, mand c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n representsthe number of cities numbered from 1 to n. Following m lines, each line hasthree integers i, j and k, represent a road between city i and city j, withlength k. Last c lines, two integers i, j each line, indicates a query of cityi and city j.

 

 

Output

For each problem instance, oneline 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

2009 Multi-University Training Contest 8 - Host byBJNU

  

Recommend

gaojie


题目意思是说:给你N个节点,给你M条边,然后C条查询,查询两个点之间的距离。
如果两点不在同一颗树上,那么这两点也就不存在什么距离。这时候输出“Not connected”;
这道题目可以转换成LCA来做。如果人工模拟求两点间距离,也是要从两个点出发向上沿着路走,汇聚到一点。就是这个算法的思想。
两点间距离可以转化为两点到LCA的距离和减去 两倍的LCA到根节点的距离。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
#define N 10050*2
using namespace std;
int n,m,num,cnt;
struct node
{
	int to,next,cost;
}e[N];
int head[N],dis[N],depth[N];
int pre[N],fa[250][N];
int vis[N];
void init()
{
	cnt=0;
	for(int i=1;i<=n;i++)//用并查集来查找两点是否在同一颗树上
		pre[i]=i;//初始化并查集
	memset(e,0,sizeof e);//初始化建边
	memset(head,-1,sizeof head);
	memset(dis,0,sizeof dis);//初始化树深,距离
	memset(depth,0,sizeof depth);
	memset(vis,0,sizeof vis);
	memset(fa,-1,sizeof fa);

}
int getfa(int x)//并查集
{
	if(x==pre[x])
		return x;
	else
		return pre[x]=getfa(pre[x]);
}
void merge(int u,int v)//合并到同一颗树上
{
	int t1,t2;
	t1=getfa(u);
	t2=getfa(v);
	if(t1!=t2)
		pre[t1]=t2;
}
void addedge(int u,int v,int w)//建边
{
    e[cnt].to=u;
    e[cnt].cost=w;
    e[cnt].next=head[v];
    head[v]=cnt++;
}
void dfs(int u,int f)//搜索树,更新距离,树深
{
	vis[u]=1;
	for(int i=head[u];~i;i=e[i].next)
	{
		int To=e[i].to;
		if(To==f||vis[To])	continue;
		dis[To]=dis[u]+e[i].cost;
		depth[To]=depth[u]+1;
		fa[0][To]=u;
		dfs(To,u);
	}
}
void solve()//树上倍增法
{
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])
			dfs(i,-1);
	}
	for(int i=0;i+1<15;i++)
	{
		for(int j=1;j<=n;j++)
			if(fa[i][j]<0)
				fa[i+1][j]=-1;
			else
				fa[i+1][j]=fa[i][fa[i][j]];
	}
}
int lca(int u,int v)//LCA倍增法在线查询
{
	if(depth[u]>depth[v])
		swap(u,v);
	for(int i=0;i<=15;i++)
	{
		if((depth[v]-depth[u])>>i&1)
			v=fa[i][v];
	}

	if(u==v)
		return v;
	for(int i=15;i>=0;i--)
	{
		if(fa[i][u]!=fa[i][v])
		{
			u=fa[i][u];
			v=fa[i][v];
		}
	}
	return fa[0][v];
}
int main()
{
	int i,a,b,c;
	while(scanf("%d%d%d",&n,&m,&num)!=EOF)
	{
		init();
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			addedge(a,b,c);
			addedge(b,a,c);
			merge(a,b);
		}
		solve();
		for(int i=1;i<=num;i++)
		{
			scanf("%d%d",&a,&b);
			int t1=getfa(a);
			int t2=getfa(b);
			if(t1==t2)//在同一颗树上
				printf("%d\n",dis[a]+dis[b]-2*dis[lca(a,b)]);
			else
				printf("Not connected\n");
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值