Educational Codeforces Round 51: F. The Shortest Statement(最短路+LCA)
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;
}