HDU - 2586 How far away ?(tarjan離線做法求lca)

How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17653    Accepted Submission(s): 6836


Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
 

Input
First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 

Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 

Sample Input
2 3 2 1 2 10 3 1 15 1 2 2 3 2 2 1 2 100 1 2 2 1
 

Sample Output
10 25 100 100
 

Source
 

     題意:

n個點n-1條邊的無向聯通圖,有m個詢問,詢問兩點間的最小距離。

   分析:

        求lca的模板題,之前寫過倍增法求lca的在線求法,這次用tarjan離線方法做一下~

        (一開始想用帶權並查集所以在並查集的時候使用了路徑優化導致一直wa~~

#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
struct node
{
	int v,w;
	node(){}
	node(int vv,int ww)
	{
		v=vv;w=ww;
	}
};
struct edge
{
	int u,v,lca;
	edge(){}
	edge(int uu,int vv,int ll)
	{
		u=uu,v=vv,lca=ll;
	}
};
vector<edge>G;
vector<node>v[50000];
vector<int>g[50000];
int father[50000],rank1[50000];
void addedge(int a,int b)
{
	G.push_back(edge(a,b,-1));
	G.push_back(edge(b,a,-1));
	int m=G.size();
	g[a].push_back(m-2);
	g[b].push_back(m-1);
}
int dir[50000];
void init(int n)
{
	for(int i=0;i<=n;i++)
	{
		father[i]=i;
		rank1[i]=0;
	}
	memset(dir,0,sizeof(dir));
}
int find(int a)
{
	if(a==father[a])
	return a;
	return father[a]=find(father[a]);
}

void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x!=y)
    father[y]=x;
}


/*bool unite(int a,int b)
{
	int aa=find(a);
	int bb=find(b);
	if(aa==bb)
		return true;
	if(rank1[aa]<rank1[bb])
	{
		father[aa]=bb;
	}
	else 
	{
		father[bb]=aa;
		if(rank1[aa]==rank1[bb])
		rank1[aa]++;
	}
	return false;
}
*/

int vis[50000];
void tarjan(int x)
{
    vis[x]=1;
	for(int i=0;i<v[x].size();i++)
	{
		int y=v[x][i].v;
		
		if(vis[y])
		continue;
		dir[y]=dir[x]+v[x][i].w;
		tarjan(y);
		unite(x,y);
		//printf("!! %d %d %d %d\n",x,y,find(x),find(y));
	}
	for(int i=0;i<g[x].size();i++)
	{
		edge & y=G[g[x][i]];
		if(vis[y.v])
		{
			G[g[x][i]].lca=G[g[x][i]^1].lca=find(y.v);
		}
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		
		int n,m;
		scanf("%d%d",&n,&m);
		init(n);
		for(int i=0;i<=n;i++)
		v[i].clear(),g[i].clear();
		G.clear();
		for(int i=0;i<n-1;i++)
		{
			int a,b,w;
			scanf("%d%d%d",&a,&b,&w);
			v[a].push_back(node(b,w));
			v[b].push_back(node(a,w));
		}
		for(int i=0;i<m;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			addedge(a,b);
		}
		memset(vis,0,sizeof(vis));
		tarjan(1);
		for(int i=0;i<m;i++)
		{
			int y=i*2,a=G[y].u,b=G[y].v,lcaa=G[y].lca;
			printf("%d\n",dir[a]+dir[b]-dir[lcaa]*2);
		}
	}
} 
/*
9
9 4
1 2 1
1 3 1
2 4 1
2 5 1
3 6 1
5 7 1
5 8 1
7 9 1
9 8
4 6
7 5
5 3
*/


AC代碼:



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