版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/82800970
题意
给出一个边比点数多至多20条的无向连通图,每条边有一个边权,多次询问两点间最短路。
分析
首先我们选出其中n-1条边建出一颗树,然后将多余的m-n+1条边的两个端点取出来,对所有点跑最短路,由于 ,那么我们取出的点最多不会超过 个,我们可以使用Floyd或dijkstra甚至spfa来求最短路。然后对于每次询问,我们枚举每个取出来的点,然后将这个点与两个询问点的最短路加起来然后和树上这两点距离取min就是答案了,总复杂度 。
Code
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=100500;
const long long inf=1e15;
vector<int>P,vis,F[maxn];
int n,m,exi[maxn],gra[18][maxn],dep[maxn];
ll sum[maxn],dis[45][maxn],len[maxn];
struct Edge {
int u,v,w;
Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
vector<Edge>edges;
inline void addedge(int u,int v,int w) {
edges.push_back(Edge(u,v,w));
edges.push_back(Edge(v,u,w));
vis.push_back(0),vis.push_back(0);
F[u].push_back(edges.size()-2);
F[v].push_back(edges.size()-1);
}
inline void dfs(int u,int f) {
gra[0][u]=f;
for(int i=1;i<18;++i)
gra[i][u]=gra[i-1][gra[i-1][u]];
for(int i=0;i<(int)F[u].size();++i) {
int p=F[u][i];
Edge &e=edges[p];
int v=e.v;
if(v==f)
continue;
// cout<<u<<" -> "<<v<<" "<<exi[v]<<endl;
if(exi[v])
continue;
exi[v]=1;
vis[p]=vis[p^1]=1;
len[v]=len[u]+e.w;
dep[v]=dep[u]+1;
dfs(v,u);
}
}
inline int lca(int x,int y) {
if(dep[x]<dep[y])
swap(x,y);
for(int d=dep[x]-dep[y],i=17;~i;--i)
if(d>>i&1)
x=gra[i][x];
if(x==y)
return x;
for(int i=17;~i;--i)
if(gra[i][x]!=gra[i][y])
x=gra[i][x],y=gra[i][y];
return gra[0][x];
}
struct node {
ll d;
int u;
node(ll d=0,int u=0):d(d),u(u){}
inline bool operator < (const node &rhs) const {
return u>rhs.u;
}
};
inline void spfa(int S) {
for(int i=1;i<=n;i++)
dis[S][i]=inf;
priority_queue<node>q;
int val=P[S];
dis[S][val]=0;
q.push(node(0,val));
while(!q.empty()) {
int u=q.top().u;q.pop();
for(int i=0;i<(int)F[u].size();i++) {
Edge &e=edges[F[u][i]];
int v=e.v,cost=e.w;
if(dis[S][v]>dis[S][u]+cost)
dis[S][v]=dis[S][u]+cost,q.push(node(dis[S][v],v));
}
}
}
int main() {
read(n),read(m);
for(int i=1,a,b,c;i<=m;i++)
read(a),read(b),read(c),addedge(a,b,c);
exi[1]=1;
dfs(1,0);
for(int i=0,a,b;i<(int)vis.size();i+=2) {
// cout<<i<<" "<<vis[i]<<endl;
if(vis[i])
continue;
a=edges[i].u,b=edges[i].v;
P.push_back(a);
P.push_back(b);
}
// for(int i=0;i<(int)P.size();++i)
// cout<<P[i]<<" ";
// cout<<endl;
sort(P.begin(),P.end());
P.resize(unique(P.begin(),P.end())-P.begin());
for(int i=0;i<(int)P.size();i++)
spfa(i);
int q,a,b;
read(q);
while(q--) {
read(a),read(b);
int l=lca(a,b);
ll ans=len[a]+len[b]-len[l]*2;
for(int i=0;i<(int)P.size();i++)
ans=min(ans,dis[i][a]+dis[i][b]);
printf("%lld\n",ans);
}
}