Educational Codeforces Round 51: F. The Shortest Statement(最短路+LCA)

版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/82799528

F. The Shortest Statement

题意:

n个点m条边(m≤n+20)的无向连通图,Q次询问,每次求出给定两点的最短路

思路:

将题意转换一下,给你一棵n个节点的树,并且这个树上还有不超过21个传送门,Q次询问,每次求出两点之间最短路

思路很简单:将和传送门直接相连的不超过42个点,求出它们与其它所有点的最短路

之后对于每次询问x, y,答案就是min(dis(x, y),  dis(x, w)+dis(w, y)),其中dis(x, y)表示x到y的树上距离,可以用lca求出,dis(x, w)表示x点到w的最短路,其中w是所有和传送门直接相连的点

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
#define LL long long
typedef struct
{
	int x, y;
	LL len;
}Road;
vector<Road> F[100005], G[100005];
queue<int> q;
Road now, temp;
LL dp[100005][43], bet[100005][19];
int cnt, vis[100005], P[105], flag[100005], fa[100005][19], deep[100005];
void Sech(int u, int p)
{
	int i, v;
	vis[u] = 1;
	for(i=0;i<F[u].size();i++)
	{
		v = F[u][i].y;
		if(v==p)
			continue;
		if(vis[v]==1)
		{
			P[++cnt] = u, P[++cnt] = v;
			continue;
		}
		now.y = v, now.len = F[u][i].len;
		G[u].push_back(now);
		now.y = u, now.len = F[u][i].len;
		G[v].push_back(now);
		Sech(v, u);
	}
}
void GetMin(int x)
{
	LL val;
	int i, now, y;
	now = P[x];
	dp[now][x] = 0;
	q.push(now), vis[now] = 1;
	while(q.empty()==0)
	{
		now = q.front();
		q.pop(), vis[now] = 0;
		for(i=0;i<F[now].size();i++)
		{
			y = F[now][i].y;
			if(dp[y][x]>dp[now][x]+F[now][i].len)
			{
				dp[y][x] = dp[now][x]+F[now][i].len;
				if(vis[y]==0)
				{
					q.push(y);
					vis[y] = 1;
				}
			}
		}
	}
}
void SechLCA(int x)
{
	int i, v;
	deep[x] = deep[fa[x][0]]+1;
	for(i=0;i<G[x].size();i++)
	{
		v = G[x][i].y;
		if(v==fa[x][0])
			continue;
		fa[v][0] = x;
		bet[v][0] = G[x][i].len;
		SechLCA(v);
	}
}
LL Query(int x, int y)
{
	int j;
	LL ans = 0;
	if(deep[x]<deep[y])
		swap(x, y);
	for(j=18;j>=0;j--)
	{
		if(deep[fa[x][j]]>=deep[y])
		{
			ans += bet[x][j];
			x = fa[x][j];
		}
	}
	if(x==y)
		return ans;
	for(j=18;j>=0;j--)
	{
		if(fa[x][j]!=fa[y][j])
		{
			ans += bet[x][j];
			ans += bet[y][j];
			x = fa[x][j];
			y = fa[y][j];
		}
	}
	ans += bet[x][0];
	ans += bet[y][0];
	return ans;
}

int main(void)
{
	LL ans;
	int n, m, i, j, x, y, len, Q;
	scanf("%d%d", &n, &m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d", &x, &y, &len);
		now.y = y, now.len = len;
		F[x].push_back(now);
		now.y = x;
		F[y].push_back(now);
	}
	Sech(1, 0);
	SechLCA(1);
	for(j=1;j<=18;j++)
	{
		for(i=1;i<=n;i++)
		{
			fa[i][j] = fa[fa[i][j-1]][j-1];
			bet[i][j] = bet[i][j-1]+bet[fa[i][j-1]][j-1];
		}
	}
	sort(P+1, P+cnt+1);
	cnt = unique(P+1, P+cnt+1)-(P+1);
	memset(vis, 0, sizeof(vis));
	memset(dp, 62, sizeof(dp));
	for(i=1;i<=cnt;i++)
		GetMin(i);
	scanf("%d", &Q);
	while(Q--)
	{
		scanf("%d%d", &x, &y);
		ans = Query(x, y);
		for(i=1;i<=cnt;i++)
			ans = min(ans, dp[x][i]+dp[y][i]);
		printf("%I64d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/82799528