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
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.
題意:
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代碼: