传送门: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 ui, vi, 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;
}