Gym - 101808K Another Shortest Path Problem (Damascus University Collegiate)【并查集+LCA】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39396954/article/details/81906878

传送门:http://codeforces.com/gym/101808/problem/K

Shortest path problems have always been a part of competitive programming, appearing in many contests all around the world. In order to keep that tradition, we created another one:

You are given an undirected connected weighted graph with N nodes and N edges, and you have to answer Q queries. Each query consists of two nodes X and Y, and you have to find the length of the shortest path between nodes X and Y.

Input

The first line contains a single integer T, the number of test cases.

Each test case starts with a line containing two integers N and Q, the number of nodes (and edges) and the number of queries. (3 ≤ N ≤ 105) (1 ≤ Q ≤ 105)

Each of the following N lines contain the description of the edges. The ith line contains 3 space-separated integers uivi, and wi. This means that there is an undirected edge between nodes ui and vi, with a weight of wi. (1 ≤ ui, vi ≤ N) (1 ≤ wi ≤ 105)

Then Q lines follow, the ith line contains two integers X and Y. This means that you need to find the shortest path between nodes X and Y. (1 ≤ X, Y ≤ N)

It is guaranteed that the graph contains no self loops or multiple edges.

Output

For each test case, and for each query, print one line containing one integer, the shortest path between X and Y.

Example

Input

1
6 3
1 2 2
1 3 4
2 6 3
3 4 1
3 5 10
3 6 6
1 4
2 5
3 2

Output

5
16
6

题意:n个点,n条路,给q个询问,每次给x,y,问x到y最短距离。

思路:n条路-1就是个树啦,所以考虑把成环的边去掉。使用并查集找到那个边,不加入图。记录它为c和d。对每组xy,用lca找到公共祖先r。如果没有那条路,就是x在图上走到y的距离,ans1。如果要走那条路,就必走它,考虑两种情况,从x到c,c到d,d到y,为ans2,从x到d,d到c,c到y,为ans3.取三者最小值即可。

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const ll maxv=1e5+5;

ll head[maxv],vis[maxv],d[maxv],dist[maxv],fa[maxv][20];
ll n,m,edgenum,ans,ans1,ans2,ans3,cc,dd,e;


ll ff[maxv];

ll findfa(ll x)
{
	ll a=x;
	while(x!=ff[x])
	{
		x=ff[x];
	}
	while(a!=ff[a])
	{
		ll z=a;
		a=ff[a];
		ff[z]=x;
	}
	return x;
}

ll uni(ll a,ll b)
{
	ll faa=findfa(a);
	ll fbb=findfa(b);
	if(faa==fbb)
	{
		cc=a,dd=b;
		return 1;
	}
	if(faa!=fbb)
	{
		ff[faa]=fbb;
		return 0;
	}
}

struct node
{
	ll val,to,next;
}edge[maxv<<1];

void init()
{
	fill(d,d+maxv,0);
	fill(head,head+maxv,-1);
	for(ll i=0;i<maxv;i++)
	{
		ff[i]=i;
		fill(fa[i],fa[i]+20,0);
	}
	edgenum=0;
}

void addedge(ll u,ll v,ll w)
{
	edge[edgenum].to=v;
	edge[edgenum].val=w;
	edge[edgenum].next=head[u];
	head[u]=edgenum++;
}

void bfs()
{
	fill(dist,dist+maxv,0);
	queue<ll>q;
	q.push(1);
	d[1]=1;
	while(!q.empty())
	{
		ll now=q.front();
		q.pop();
		for(ll i=head[now];i!=-1;i=edge[i].next)
		{
			ll y=edge[i].to;
			if(d[y])
				continue;
			d[y]=d[now]+1;
			dist[y]=dist[now]+edge[i].val;
			fa[y][0]=now;
			for(ll j=1;j<20;j++)
			{
				fa[y][j]=fa[fa[y][j-1]][j-1];
			}
			q.push(y);
		}
	}
}

ll lca(ll x,ll y)
{
	if(d[x]>d[y])
		swap(x,y);
	for(ll i=19;i>=0;i--)
	{
		if(d[fa[y][i]]>=d[x])
			y=fa[y][i];
	}
	if(x==y)
		return x;
	for(ll i=19;i>=0;i--)
	{
		if(fa[x][i]!=fa[y][i])
			x=fa[x][i],y=fa[y][i];
	}
	return fa[x][0];
}

int main()
{
	ll t;
	scanf("%lld",&t);
	while(t--)
	{
		init();
		scanf("%lld%lld",&n,&m);
		ll u,v,w;
		for(ll i=1;i<=n;i++)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			if(uni(u,v)==1)
			{
				e=w;
			}
			else
			{
				addedge(u,v,w);
				addedge(v,u,w);
			}
		}
		bfs();
		while(m--)
		{
			ll a,b;
			scanf("%lld%lld",&a,&b);
			ll root=lca(a,b);
			ans1=dist[a]+dist[b]-2*dist[root];
			ans2=e+dist[a]+dist[cc]-2*dist[lca(a,cc)]+dist[dd]+dist[b]-2*dist[lca(dd,b)];
			ans3=e+dist[a]+dist[dd]-2*dist[lca(a,dd)]+dist[cc]+dist[b]-2*dist[lca(cc,b)];
			ans=min(ans1,ans2);
			ans=min(ans,ans3);
			printf("%lld\n",ans);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39396954/article/details/81906878
今日推荐