1. 程式人生 > >2018.09.24 codeforces 1051F. The Shortest Statement(dijkstra+lca)

2018.09.24 codeforces 1051F. The Shortest Statement(dijkstra+lca)

傳送門 這真是一道一言難盡的題。 首先比賽的時候居然沒想出來正解。 其次賽後除錯一直調不出來最後發現是depth傳錯了。 其實這是一道簡單題啊。 對於樹邊直接lca求距離。 由於非樹邊最多21條。 因此我們對這21條邊連線的42個點都跑一次最短路來更新答案的最小值即可。 程式碼:

#include<bits/stdc++.h>
#define N 100005
#define ll long long
#define pii pair<int,int>
#define pli pair<ll,int>
#define fi first
#define se second
using namespace std; inline ll read(){ ll ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } int n,m,q,st[N][21],first[N],stk[N],dep[N],cnt=0,tot=0,top=0; ll w[N],dis[45][N]; bool vis[N]; struct edge{int
v,next;ll w;}e[N<<1]; inline void add(int u,int v,ll w){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].w=w,first[u]=cnt;} inline void dfs(int p,int fa){ vis[p]=true; for(int i=1;i<=20;++i)st[p][i]=st[st[p][i-1]][i-1]; for(int i=first[p];i;i=e[i].next){ int v=e[i].v; if(v==fa)continue; if
(!vis[v])w[v]=w[p]+e[i].w,st[v][0]=p,dep[v]=dep[p]+1,dfs(v,p); else stk[++top]=p,stk[++top]=v; } } inline int lca(int x,int y){ if(dep[x]<dep[y])x^=y,y^=x,x^=y; int tmp=dep[x]-dep[y]; for(int i=20;~i;--i)if(tmp>>i&1)x=st[x][i]; if(x==y)return x; for(int i=20;~i;--i)if(st[x][i]!=st[y][i])x=st[x][i],y=st[y][i]; return st[x][0]; } inline void dijkstra(int s,int siz){ priority_queue<pli,vector<pli>,greater<pli> >q; for(int i=1;i<=n;++i)dis[siz][i]=1e18,vis[i]=false; q.push(pli(dis[siz][s]=0,s)); while(!q.empty()){ int x=q.top().se; q.pop(); if(vis[x])continue; vis[x]=true; for(int i=first[x];i;i=e[i].next){ int v=e[i].v; if(dis[siz][v]>dis[siz][x]+e[i].w)dis[siz][v]=dis[siz][x]+e[i].w,q.push(pli(dis[siz][v],v)); } } } int main(){ n=read(),m=read(); for(int i=1;i<=m;++i){ int u=read(),v=read(); ll w=read(); add(u,v,w),add(v,u,w); } dfs(1,0); sort(stk+1,stk+top+1),top=unique(stk+1,stk+top+1)-stk-1; for(int i=1;i<=top;++i)dijkstra(stk[i],i); q=read(); while(q--){ int u=read(),v=read(); ll ans=w[u]+w[v]-2*w[lca(u,v)]; for(int i=1;i<=top;++i)ans=min(ans,dis[i][u]+dis[i][v]); cout<<ans<<'\n'; } return 0; }