(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
题目:传送门
(原题目描述及样例在最下面。)
大概是这个意思,给你一个n个节点的树和额外一条边,每条边都有权值,m次询问,问节点a和b的最短距离。
思路:
首先不算额外的那条边,树上任意两点的权值是固定的。
那么额外的一条边可以带来什么呢?
假设额外的一条边为XY,权值为Z。
对于一颗树,我们可以dfs预处理处每个节点 i 到1号节点的距离dis[i]
而树上任意两点a,b的距离len=dis[a]+dis[b]-2*dis[LCA(a,b)]
有可能a和b通过这条额外的边会有更短的距离
ans = min( len(a,b), len(a,X)+len(b,Y)+Z, len(a,Y)+len(b,X)+Z )
所以现在问题就在求LCA,我用的是倍增的方法
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+7;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct lp{
int v,nex;
LL w;
}cw[N*10];
int fa[N],head[N],dep[N],f[N][30];
LL size[N],dis[N];
int n,m,tot,X,Y;
LL Z;
void add(int x,int y,int z){
cw[++tot].v=y;cw[tot].w=z*1LL;cw[tot].nex=head[x];
head[x]=tot;
cw[++tot].v=x;cw[tot].w=z*1LL;cw[tot].nex=head[y];
head[y]=tot;
}
void init(){
tot=-1;
memset(head,-1,sizeof(head));
memset(fa,0,sizeof(fa));
memset(f,0,sizeof(f));
memset(dep,0,sizeof(dep));
memset(size,0,sizeof(size));
memset(dis,0,sizeof(dis));
}
void dfs(int u,int Fa,int h){
dep[u]=h;f[u][0]=Fa;fa[u]=Fa;
for(int i=1;i<20;++i){
int cf=f[u][i-1];
f[u][i]=f[cf][i-1];
}
for(int i=head[u];~i;i=cw[i].nex){
int v=cw[i].v;
if(v==Fa)continue;
dis[v]=dis[u]+cw[i].w;
dfs(v,u,h+1);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])x^=y^=x^=y;
for(int i=19;i>=0;--i){
if(dep[f[x][i]]>=dep[y]){
x=f[x][i];
}
}
if(x==y)return x;
for(int i=19;i>=0;--i){
if(f[x][i]!=f[y][i]){
x=f[x][i];y=f[y][i];
}
}
return f[x][0];
}
LL Len(int a,int b){
int ff=LCA(a,b);
return (dis[a]+dis[b]-2*dis[ff]);
}
int main(){
int T, u,v,w;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
init();
for(int i=0;i<n-1;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
scanf("%d%d%d",&X,&Y,&Z);
dfs(1,0,0);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
LL ans=min(INF,Len(a,b));
ans=min(ans,min(Len(a,X)+Len(b,Y)+Z,Len(a,Y)+Len(b,X)+Z));
printf("%lld\n",ans );
}
}
return 0;
}
题目描述:
outputstandard output
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
inputCopy
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
outputCopy
5
16
6