Castle
- Time Limit: 1s
- Memory Limit: 128.0 MB
Description
The cosmic leader Loki is exploring a castle full of treasure. The castle can be considered as a connected undirected graph with NN vertices and N
N edges. Teleporting is a common skill among the dwellers of the Chaobuli star. However before Loki teleports he has to know the distance between the destination point and the starting point. Help Loki find the shortest distance between Q
Q pairs of vertices.
Input
The first line contains a single integer TT denoting the number of test cases. For each test case, the first line contains two integers N
N and Q
Q meaning as above. N
N lines follow, each containing three integers u,v,w
u,v,w meaning there's an undirected edge between vertex u
u and vertex v
v with weight w
w . No edges will be given more than once. Each of the next Q
Q lines contains a pair of vertices u,v
u,v denoting a query.
Output
For each test case print
Q
Q
lines, each containing a single integer denoting the shortest distance between the given vertices.
Sample Input 1
1 4 2 0 1 3 1 2 1 2 3 1 3 0 2 1 3 0 2
Sample Output 1
2 3
题意:给出一个包含n个点,n条边的无向图,图中不包含重边。
给出q个询问,每次需要回答从u到v的最短路。保证图联通
给出q个询问,每次需要回答从u到v的最短路。保证图联通
题解:图就是一棵树+一条额外边
那么对于每次询问 我们可以查出走这条额外的边的值和不走的值 取个min
对于距离 用rmq预处理出lca 然后o1查询lca
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,head[30005],cnt,tot,dpp[30005];
struct node{
int to,nex,wei;
}edge[60005];
const int MAXN = 30010;
int F[MAXN*2];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
int P[MAXN];//P[i]表示点i在F中第一次出现的位置
void add(int u,int v,int w){
edge[tot].to=v;
edge[tot].wei=w;
edge[tot].nex=head[u];
head[u]=tot++;
}
int rmq[2*MAXN],pre[MAXN];//rmq数组,就是欧拉序列对应的深度序列
int find(int x){
if(pre[x]!=x){
int r=find(pre[x]);
pre[x]=r;
}
return pre[x];
}
struct ST
{
int mm[2*MAXN];
int dp[2*MAXN][20];//最小值对应的下标
void init(int n)
{
mm[0] = -1;
for(int i = 1;i <= n;i++)
{
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = i;
}
for(int j = 1; j <= mm[n];j++)
for(int i = 1; i + (1<<j) - 1 <= n; i++)
dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
}
int query(int a,int b)//查询[a,b]之间最小值的下标
{
if(a > b)swap(a,b);
int k = mm[b-a+1];
return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
}
}st;
void dfs(int u,int pre,int dep,int sum)
{
dpp[u]=sum;
F[++cnt] = u;
rmq[cnt] = dep;
P[u] = cnt;
for(int i = head[u];i != -1;i = edge[i].nex)
{
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u,dep+1,sum+edge[i].wei);
F[++cnt] = u;
rmq[cnt] = dep;
}
}
void LCA_init(int root,int node_num)//查询LCA前的初始化
{
cnt = 0;
dfs(root,root,0,0);
st.init(2*node_num-1);
}
int query_lca(int u,int v)//查询u,v的lca编号
{
return F[st.query(P[u],P[v])];
}
int main(){
int t,q,i,j;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++)pre[i]=i;
cnt=tot=0;
int u,v,w;
int us,vs,ws;
for(i=1;i<=n;i++){
scanf("%d%d%d",&u,&v,&w);
u++;
v++;
if(find(u)==find(v)){
us=u;
vs=v;
ws=w;
continue;
}
pre[find(u)]=v;
add(u,v,w);
add(v,u,w);
}
LCA_init(1,n);
while(q--){
scanf("%d%d",&u,&v);
u++;
v++;
int zu=query_lca(u,v),ans1,ans2,ans3;
ans1=dpp[u]+dpp[v]-2*dpp[zu];
int zu1=query_lca(u,us),zu2=query_lca(v,vs);
ans2=dpp[u]+dpp[us]-2*dpp[zu1]+dpp[v]+dpp[vs]-2*dpp[zu2]+ws;
zu1=query_lca(u,vs);
zu2=query_lca(v,us);
ans3=dpp[u]+dpp[vs]-2*dpp[zu1]+dpp[v]+dpp[us]-2*dpp[zu2]+ws;
printf("%d\n",min(ans1,min(ans2,ans3)));
}
}
return 0;
}