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
#include
#include
#include
#include
#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;
}



你可能感兴趣的:(HDU-2874 Connections between cities(倍增法))