版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84778174
这道题题意很简单
给你一个森林,输入连通的点,最后给你多次询问,每次问输出两个点 s 和 t 之间的 距离
如果没连通就输出 Not contence....(总之是串英文)
有些丢人。。。不会写离线算法。。写了个在线算法。。。跑了 1700ms 。。。
还是很好搞的。。因为是森林。跑最短路会出事的。所以先用并查集建立集合关系。
输入s t 判断一下,之后正常的求出 dis[s] + dis[t] - 2 * dis[lca]
扫描二维码关注公众号,回复:
4491809 查看本文章
以下是 AC 代码。。。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1e5+5;
const int ins = 20;
int f[maxn][ins];
int pre[maxn];
int dis[maxn];
int dep[maxn];
struct node
{
int to,nex,val;
}ed[maxn<<1];
int head[maxn],tot;
int n,m,q;
void add(int u,int v,int w)
{
ed[++tot].to = v;
ed[tot].val = w;
ed[tot].nex = head[u];
head[u] = tot;
}
void init()
{
tot = 0;
for(int i = 0; i <= n; i++)
pre[i] = i;
memset(head , -1, sizeof(head));
memset(f, 0, sizeof(f));
memset(dis, 0, sizeof(dis));
memset(dep, 0, sizeof(dep));
}
int findd(int x)
{
return x == pre[x] ? x : pre[x] = findd(pre[x]);
}
void merage(int a,int b)
{
int aa = findd(a), bb = findd(b);
if(aa != bb)
pre[aa] = bb;
}
void dfs(int x,int p,int d)
{
f[x][0] = p;
dep[x] = dep[p] + 1;
dis[x] = d;
for(int i=1;i<=19;i++)
{
f[x][i] = f[f[x][i - 1]][i - 1];
}
for(int i=head[x];~i;i=ed[i].nex)
{
int v = ed[i].to;
if(v != p)
{
dfs(v, x, dis[x] + ed[i].val);
}
}
}
int lca(int a,int b)
{
if(dep[a] > dep[b])
swap(a,b);
for(int i=19;i>=0;i--)
{
if(dep[f[b][i]] >= dep[a])
b = f[b][i];
}
if(a == b)
return a;
for(int i=19;i>=0;i--)
{
if(f[a][i] != f[b][i])
{
a = f[a][i];
b = f[b][i];
}
}
return f[a][0];
}
int main()
{
while(scanf("%d%d%d",&n,&m,&q) == 3)
{
int u,v,w;
init();
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
merage(u,v);
}
for(int i=1;i<=n;i++)
{
if(pre[i] == i)
dfs(i, 0, 0);
}
while(q--)
{
scanf("%d%d",&u,&v);
if(findd(u) == findd(v))
printf("%d\n",dis[u] + dis[v] - 2 * dis[lca(u, v)]);
else
printf("Not connected\n");
}
}
return 0;
}