POJ1986(Distance Queries)

Distance Queries

Description

Farmer John’s cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists of the same input as in “Navigation Nightmare”,followed by a line containing a single integer K, followed by K “distance queries”. Each distance query is a line of input containing two integers, giving the numbers of two farms between which FJ is interested in computing distance (measured in the length of the roads along the path between the two farms). Please answer FJ’s distance queries as quickly as possible!
Input

  • Lines 1…1+M: Same format as “Navigation Nightmare”

  • Line 2+M: A single integer, K. 1 <= K <= 10,000

  • Lines 3+M…2+M+K: Each line corresponds to a distance query and contains the indices of two farms.
    Output

  • Lines 1…K: For each distance query, output on a single line an integer giving the appropriate distance.

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6
Sample Output

13
3
36

思路

給定一張無向圖,圖的點數和無向邊數不知道(暫定一個10w個點,10w條無向邊),然後有m行每行給定兩個點和距離,以及方位。(方位沒個卵子用),之後有k行每行給定一對點問這兩點之間的距離。倍增LCA求出兩點的最近公共祖先,然後兩點的距離就是dist[x] + dist[y] - 2*dist[lca],這道題還有個毛病沒說圖連不連通,這個到好解決直接上並查集。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 100005;
const int maxd = 19;
struct edge{
	int to;
	int w; 
	int next;
}e[maxn<<1];
int f[maxn][20];
int s[maxn];
int dep[maxn];
int dist[maxn];
int head[maxn];
int tot;
inline void addedge(int x,int y,int z)
{
	e[tot].to = y;
	e[tot].w = z;
	e[tot].next = head[x];
	head[x] = tot++;
}
void clear_set()
{
	tot = 0;
	memset(dist,0,sizeof(dist));
	memset(head,-1,sizeof(head));
	memset(dep,0,sizeof(dep));
	memset(f,0,sizeof(f));
	for(int i = 0;i < maxn;i++){
		s[i] = i;
	}
}
int find_set(int x)
{
	if(x != s[x]){
		s[x] = find_set(s[x]);
	}
	return s[x];
}
inline void dfs(int x,int fx)
{
	dep[x] = dep[fx] + 1;
	f[x][0] = fx;
	for(int i = 1;i <= maxd;i++){
		f[x][i] = f[f[x][i-1]][i-1];
	}	
	for(int i = head[x];~i;i = e[i].next){
		if(e[i].to == fx)	continue;
		dist[e[i].to] = dist[x] + e[i].w;
		dfs(e[i].to,x);
	}
}
int LCA(int x,int y)
{
	if(dep[x] < dep[y])		swap(x,y);
	int d = dep[x] - dep[y];
	for(int i = 0;i <= maxd;i++){
		if(((1<<i)&d)){
			x = f[x][i];
		}
	}
	if(x == y)		return x;
	for(int i = maxd;i >= 0;i--){
		if(f[x][i] != f[y][i]){
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}
int main()
{
	int n,m,q;
	while(~scanf("%d%d",&n,&m)){
		clear_set();
		int x,y,z;
		char str[5];			//方位沒用 
		for(int i = 0;i < m;i++){
			scanf("%d%d%d%s",&x,&y,&z,str);
			int fx = find_set(x);
			int fy = find_set(y);
			if(fx != fy)	s[fx] = fy;
			addedge(x,y,z);addedge(y,x,z);
		}
		for(int i = 1;i <= n;i++){
			if(!dep[i]){
				dfs(i,0);
			}
		}
		scanf("%d",&q);
		while(q--){
			scanf("%d%d",&x,&y);
			int fx = find_set(x);
			int fy = find_set(y);
			if(fx != fy){
				printf("0\n");
				continue;	
			}
			z = LCA(x,y);
			int ans = dist[x] + dist[y] - 2*dist[z];
			printf("%d\n",ans);
		}
	}
	return 0;
}

願你走出半生,歸來仍是少年~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章