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

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82831742

传送门
这真是一道一言难尽的题。
首先比赛的时候居然没想出来正解。
其次赛后调试一直调不出来最后发现是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;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/82831742