習題:The Shortest Statement(dij&LCA)
阿新 • • 發佈:2020-08-24
題目
思路
注意到邊的數量很特殊,只比點的數量多了20不到
先建一顆生成樹,如果不用多的邊,那每兩個的之間的距離就可以直接LCA來求
考慮如果多的邊有用,設這些多的邊的端點的集合為P,那麼一定是從起點到P中的某一個元素,再到P中的另一個元素,再到終點,所以對P中的每一個元素進行一次dij,
最後的答案跟LCA進行比較即可
程式碼
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; namespace IO { void read(int &x) { x=0; int f=1; char c=getchar(); while('0'>c||c>'9') { if(c=='-') f=-1; c=getchar(); } while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } x*=f; } void read(long long &x) { x=0; int f=1; char c=getchar(); while('0'>c||c>'9') { if(c=='-') f=-1; c=getchar(); } while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } x*=f; } void write(int x) { if(x<10) putchar(x+'0'); else { write(x/10); putchar(x%10+'0'); } } void write(long long x) { if(x<10) putchar(x+'0'); else { write(x/10); putchar(x%10+'0'); } } } using namespace IO; struct node { int e; long long w; friend bool operator < (const node &a,const node &b) { return a.w>b.w; } }; int n,m,Q; int dp_ind[100005][25],dep[100005]; long long dp_w[100005][25],dis[45][100005]; bool used[100005],vis[100005]; vector<int> p; vector<node> g[100005]; priority_queue<node> q; void dfs(int u,int fa) { dep[u]=dep[fa]+1; for(int i=1;i<=20;i++) { dp_ind[u][i]=dp_ind[dp_ind[u][i-1]][i-1]; dp_w[u][i]=dp_w[u][i-1]+dp_w[dp_ind[u][i-1]][i-1]; } used[u]=1; for(int i=0;i<g[u].size();i++) { int v=g[u][i].e; if(v==fa) continue; else if(used[v]) { if(vis[u]==0) { vis[u]=1; p.push_back(u); } if(vis[v]==0) { vis[v]=1; p.push_back(v); } } else { dp_ind[v][0]=u; dp_w[v][0]=g[u][i].w; dfs(v,u); } } } long long lca(int u,int v) { long long w=0; if(u==v) return w; if(dep[u]>dep[v]) swap(u,v); for(int i=20;i>=0;i--) if(dep[u]<=dep[dp_ind[v][i]]) { w=w+dp_w[v][i]; v=dp_ind[v][i]; } if(u==v) return w; for(int i=20;i>=0;i--) { if(dp_ind[u][i]!=dp_ind[v][i]) { w=w+dp_w[u][i]; w=w+dp_w[v][i]; u=dp_ind[u][i]; v=dp_ind[v][i]; } } return w+dp_w[u][0]+dp_w[v][0]; } void dij(int s,long long *dis) { q.push((node){s,0}); while(!q.empty()) { node t=q.top(); q.pop(); if(t.w>dis[t.e]) continue; dis[t.e]=t.w; for(int i=0;i<g[t.e].size();i++) { int v=g[t.e][i].e; if(t.w+g[t.e][i].w<dis[v]) q.push((node){v,t.w+g[t.e][i].w}); } } } int main() { memset(dis,0x3f,sizeof(dis)); read(n);read(m); for(int i=1,u,v;i<=m;i++) { long long w; read(u);read(v);read(w); g[u].push_back((node){v,w}); g[v].push_back((node){u,w}); } dfs(1,0); for(int i=0;i<p.size();i++) dij(p[i],dis[i]); read(Q); for(int i=1,u,v;i<=Q;i++) { read(u);read(v); long long ans=(1ll<<60); for(int i=0;i<p.size();i++) for(int j=0;j<p.size();j++) ans=min(ans,dis[i][u]+dis[i][p[j]]+dis[j][v]); write(min(ans,lca(u,v))); putchar('\n'); } return 0; }