BZOJ 1602: [Usaco2008 Oct]牧場行走


題目


1602: [Usaco2008 Oct]牧場行走

Time Limit: 5 Sec  Memory Limit: 64 MB

Description

N頭牛(2<=n<=1000)別人被標記爲1到n,在同樣被標記1到n的n塊土地上喫草,第i頭牛在第i塊牧場喫草。 這n塊土地被n-1條邊連接。 奶牛可以在邊上行走,第i條邊連接第Ai,Bi塊牧場,第i條邊的長度是Li(1<=Li<=10000)。 這些邊被安排成任意兩頭奶牛都可以通過這些邊到達的情況,所以說這是一棵樹。 這些奶牛是非常喜歡交際的,經常會去互相訪問,他們想讓你去幫助他們計算Q(1<=q<=1000)對奶牛之間的距離。

Input

*第一行:兩個被空格隔開的整數:N和Q

 *第二行到第n行:第i+1行有兩個被空格隔開的整數:AI,BI,LI

*第n+1行到n+Q行:每一行有兩個空格隔開的整數:P1,P2,表示兩頭奶牛的編號。

Output

*第1行到第Q行:每行輸出一個數,表示那兩頭奶牛之間的距離。

Sample Input

4 2
2 1 2
4 3 2
1 4 3
1 2
3 2

Sample Output

2
7


題解


這題就是一個裸的LCA,值得高興的是我竟然是寫了一遍之後調都沒調直接交就A掉了,好開心~


代碼


/*Author:WNJXYK*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
using namespace std;

#define LL long long

inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
inline void swap(LL &x,LL &y){LL tmp=x;x=y;y=tmp;}
inline int remin(int a,int b){if (a<b) return a;return b;}
inline int remax(int a,int b){if (a>b) return a;return b;}
inline LL remin(LL a,LL b){if (a<b) return a;return b;}
inline LL remax(LL a,LL b){if (a>b) return a;return b;}

int ans[1005][20];
int dep[1005];
struct Edge{
	int u,v;
	int l;
	int nxt;
	Edge(){}
	Edge(int a,int b,int c,int d){u=a;v=b;l=c;nxt=d;}
}; 
Edge e[5005];
int head[1005];
int nume=0;
bool visited[1005];
int dist[1005];

inline void addEdge(int x,int y,int c){
	e[++nume]=Edge(x,y,c,head[x]);
	head[x]=nume;
	e[++nume]=Edge(y,x,c,head[y]);
	head[y]=nume;
}

void dfs(int x,int depth,int dists){
	visited[x]=true;
	dep[x]=depth;
	dist[x]=dists;
	for (int i=1;i<=10;i++){
		ans[x][i]=ans[ans[x][i-1]][i-1];
	}
	for (int i=head[x];i;i=e[i].nxt){
		int g=e[i].v;
		if (visited[g]==false){
			ans[g][0]=x;
			dfs(g,depth+1,dists+e[i].l);
		}
	}
}

inline void swim(int &x,int h){
	for (int i=0;h;i++){
		if (h&1) x=ans[x][i];
		h/=2;
	}
}

inline int lca(int x,int y){
	if (dep[x]<dep[y])swap(x,y);
	swim(x,dep[y]-dep[x]);
	if (x==y) return x;
	for (;;){
		int index=0;
		for (;ans[x][index]!=ans[y][index];index++);
		if (index==0) return ans[x][0];
		x=ans[x][index-1];
		y=ans[y][index-1];
	}
}

int n,Q;
int main(){
	scanf("%d%d",&n,&Q);
	for (int i=1;i<=n-1;i++){
		int x,y,c;
		scanf("%d%d%d",&x,&y,&c);
		addEdge(x,y,c);
	}
	ans[1][0]=1;
	dfs(1,1,0);
	for (int i=1;i<=Q;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		int lc=lca(x,y);
		printf("%d\n",dist[x]+dist[y]-dist[lc]*2);
	}
	return 0;
}



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