题意:
给你n个点,m条边,进行c此询问,若询问的两点是联通的,则输出两者的距离,否则输出Not connected。
首先判断是否连通,显然用并查集就可以愉快的解决。对于剩下的部分,这道题也算模板题吧(然而本蒟蒻WA了8次doge),用dis数组记录节点到根节点的距离,那么两者间的距离不就等于dis[u]+dis[v]-2*dis[lca(u,v)]了吗?
上边说过了这道题算是一道模板题,所以也没什么巧妙的地方要讲,那么就这么愉快地结束分析部分吧。我是用的倍增法,如果你不会LCA。。emmm,LCA,点击就送.
下面上代码吧
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 10020;
int head[maxn];
int depth[maxn];
int ls[maxn][20];
int pre[maxn];
int dis[maxn];
int n, m, c, cnt;
struct node {
int to;
int nxt;
int val;
}date[maxn<<1];
int find(int x) {//愉快地并查集
if (pre[x] == x) return x;
pre[x] = find(pre[x]);
return pre[x];
}
void merge(int u, int v) {//愉快的合并
int fu = find(u);
int fv = find(v);
if (fu != fv) {
pre[fu] = fv;
}
}
void addedge(int u, int v, int w) {//愉快地建边
date[++cnt] = node{ v,head[u],w };
head[u] = cnt;
}
void init_num() {//开始懒得写那么沙雕的东西
for (int i = 1; i <= n; i++) {
pre[i] = i;
}
memset(head, -1, sizeof(head));
memset(ls, 0, sizeof(ls));
memset(dis, 0, sizeof(dis));
memset(depth, 0, sizeof(depth));
cnt = 0;
}
void dfs(int x, int p) {
ls[x][0] = p;
depth[x] = depth[p] + 1;
for (int i = 1; i <= 19; i++) {
ls[x][i] = ls[ls[x][i - 1]][i - 1];
}
for (int i = head[x]; ~i; i = date[i].nxt) {
int v = date[i].to;
if (v != p){
dis[v] = dis[x] + date[i].val;
dfs(v, x);
}
}
}
int lca(int x, int y) {
if (depth[x] < depth[y]) {
swap(x, y);
}
for (int i = 19; i >= 0; i--) {//扔到同一层
if (depth[ls[x][i]]>=depth[y]) {
x = ls[x][i];
}
}
if (x == y) return x;
for (int i = 19; i >= 0; i--) {
if (ls[x][i] != ls[y][i]) {
x = ls[x][i];
y = ls[y][i];
}
}
return ls[x][0];
}
int main() {
while (scanf("%d %d %d", &n, &m, &c) != EOF) {//注意此题多组输入,我没多组输入WA了六次,卡了一天(微笑中透露疲惫.jpg)
init_num();
for (int i = 1; i <= m; i++) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
merge(u, v);
}
for (int i = 1; i <= n; i++) {
if (pre[i]==i) {
dfs(i, 0);
}
}
while (c--) {
int u, v;
scanf("%d %d", &u, &v);
if (find(u) != find(v)) {
printf("Not connected\n");
}
else {
printf("%d\n", dis[u] + dis[v] - 2 * dis[lca(u, v)]);
}
}
}
}
本文介绍如何使用并查集判断图中两点是否联通,并通过LCA算法计算两点间距离。采用倍增法实现LCA,适用于多组输入数据处理。
522

被折叠的 条评论
为什么被折叠?



