当前位置: 首页 > news >正文

拱墅区网站建设台州seo排名公司

拱墅区网站建设,台州seo排名公司,一个小外贸公司怎么开,会所类WordPress主题题意: ​ 有一个不一定连通的无向图,两点间有 \(n(n \ge 1)\) 条边,给出 \(q\) 个询问,每次询问从一个点到达另一个点的所有路径中的一条边的最小值最大是多少。如果无法到达就输出 \(-1\) 思路: ​ 首先我们可以并查集…

题意:

​ 有一个不一定连通的无向图,两点间有 \(n(n \ge 1)\) 条边,给出 \(q\) 个询问,每次询问从一个点到达另一个点的所有路径中的一条边的最小值最大是多少。如果无法到达就输出 \(-1\)

思路:

​ 首先我们可以并查集维护每个连通块,用并查集来判断询问中的两个点是否能够相连。然后我们来考虑每个连通块的情况。既然题目要询问每次询问从一个点到达另一个点的所有路径中的一条边的最小值最大是多少,那么这里很显然有一个贪心:假如我们有这个连通块的最大生成树,那么假如我们想要知道从 \(u\)\(v\) 的路径中的所有边中的最小值,这个时候我们肯定从 \(u\) 通过最大生成树上的路径到 \(v\)。所以我们可以维护一下最大生成树。

​ 之后我们要做的就是给你一个树,和树上的两个点,怎么求两个点间的路径中的某条边的最小值。我们可以这么考虑倍增:

​ 假如我们要求询问 \(u\), \(v\) 时的答案,假如\(u\), \(v\) 的LCA(最近公共祖先)是 \(t\) ,假如 \(u\)\(v\) 中的一个点就是 \(t\) ,那么说明 \(u\)\(v\) 的路径中的那个最小的边就在 \(u\)\(v\) 的路径中,也就是在从一个不是LCA的点到LCA的路径中。如果 \(u\)\(v\) 都不是他们的LCA,那么 \(u\)\(v\) 的路径中的最短的那个边在 \(u\) 到他们的 LCA 的路径或是在 \(v\) 到它们的 LCA 中的路径中。然后我们发现这个答案中的那个最短边与 LCA脱不了关系。所以我们可以考虑在倍增维护求LCA的时候顺便把答案求出来。

​ 我们设 up_point[i][j] 表示一个点从 \(i\) 号结点往上跳 \(2^j\) 步到达的点(会倍增求LCA的一定知道这个),设 min_dis[i][j] 从一个点 \(i\) 往上跳 \(2^j\) 步的路径中的最短边。然后我们可以 dfs 的时候这么维护这两个数组

up_point[i][0] = father_of_i; //边界
min_dis[i][0] = the_dis_between_i_and_father_of_it; //边界
up_point[i][j] = up_point[up_point[i][j - 1]][j - 1];
min_dis[i][j] = min(min_dis[i][j], min_dis[up_point[i][j - 1]][j - 1]);

然后我们在不断往上跳的过程中不断用途中的min_dis[i][j] 来维护答案就可以了,具体看代码。(我突然发现还是看代码可能比看上面的话更好)

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>using namespace std;const int N = 1e4 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;int n, m, q;
int u, v, w;
int f[N];    //并查集
int head[N]; //头指针
int cnt = 0; //边的数量 
int up_point[N][25];
int min_dis[N][25];
int depth[N]; //每个点的深度
bool vis[N];struct EDGE {int s;int e;int w;int nxt;
} Edge[M], tmp_Edge[M];bool cmp(EDGE a, EDGE b) {return a.w > b.w;
}inline int Min(int x, int y) {return x <= y ? x : y;
}inline void Swap(int &a, int &b) {int t = a;a = b;b = t;
}void add(int u, int v, int w) {++cnt;Edge[cnt].s = u;Edge[cnt].e = v;Edge[cnt].w = w;Edge[cnt].nxt = head[u];head[u] = cnt;
}void dfs(int x, int dep) {for (register int i = 1; i <= 20; ++i) { up_point[x][i] = up_point[up_point[x][i - 1]][i - 1];min_dis[x][i] = Min(min_dis[x][i - 1], min_dis[up_point[x][i - 1]][i - 1]);}for (register int i = head[x]; i != 0 && Edge[i].s == x; i = Edge[i].nxt) {if (vis[Edge[i].e]) continue;vis[Edge[i].e] = true;up_point[Edge[i].e][0] = x;min_dis[Edge[i].e][0] = Edge[i].w;depth[Edge[i].e] = dep + 1;dfs(Edge[i].e, dep + 1);}
}int solve(int a, int b) {int min_ans = INF;if (depth[a] < depth[b]) Swap(a, b); //让 a 为深度最大的点int k_dis = depth[a] - depth[b];for (register int i = 0; (1 << i) <= k_dis; ++i) {   //让两个点的深度一样if ((1 << i) & k_dis) {min_ans = Min(min_ans, min_dis[a][i]);a = up_point[a][i];}}if (a == b) return min_ans; else {for (register int i = 20; i >= 0; --i) {if (up_point[a][i] != up_point[b][i]) {min_ans = Min(min_ans, Min(min_dis[a][i], min_dis[b][i]));a = up_point[a][i], b = up_point[b][i];}}min_ans = Min(min_ans, Min(min_dis[a][0], min_dis[b][0])); //很重要}return min_ans;
}int get_f(int v) {if (f[v] == v) return v;else return f[v] = get_f(f[v]);
}void merge(int u, int v) {int t1 = get_f(u);int t2 = get_f(v);if (t1 != t2) f[t2] = t1; 
}inline int read() {int s = 0, w = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-') w = -1;ch = getchar();}while (ch >= '0' && ch <= '9') {s = s * 10 + ch - '0';ch = getchar();}return s * w;
}void write(int x) {if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0');
}int main() {n = read(), m = read();for (register int i = 1; i <= m; ++i) {u = read(), v = read(), w = read();tmp_Edge[i].s = u;tmp_Edge[i].e = v;tmp_Edge[i].w = w;}sort(tmp_Edge + 1, tmp_Edge + 1 + m, cmp);for (register int i = 1; i <= n; ++i) f[i] = i; //初始化并查集for (register int i = 1; i <= m; ++i) { //构建最大生成树int t1 = get_f(tmp_Edge[i].s);int t2 = get_f(tmp_Edge[i].e);if (t1 != t2) {merge(tmp_Edge[i].s, tmp_Edge[i].e);add(tmp_Edge[i].s, tmp_Edge[i].e, tmp_Edge[i].w);add(tmp_Edge[i].e, tmp_Edge[i].s, tmp_Edge[i].w);}}for (register int i = 1; i <= n; ++i) {if (f[i] == i) {vis[i] = true;dfs(i, 0);}}q = read();for (register int i = 1; i <= q; ++i) {u = read(), v = read();int t1 = get_f(u);int t2 = get_f(v);if (t1 != t2) {write(-1), putchar('\n');continue;}int ans = solve(u, v);write(ans), putchar('\n');}return 0;
}

转载于:https://www.cnblogs.com/lixiao189/p/9795281.html

http://www.lbrq.cn/news/2693557.html

相关文章:

  • 雄安做网站公司seo网站诊断方案
  • 优惠券的网站制作seo关键词优化推广价格
  • 高校网站群建设的公司有哪些企业网站设计论文
  • 徐州做网站的公司线上销售渠道有哪几种
  • 推荐网站建设石家庄网络推广
  • 做网站 域名 网站 空间济南最新消息
  • 南京网站制作域名关键词挖掘
  • wordpress软件网站模板下载网络推广平台
  • 为企业提供网站建设服务百度网盘app怎么打开链接
  • 阳谷网站建设公司安徽网站推广
  • php网站建设教程 电子书指数平滑法
  • wordpress 部署关键词推广优化排名品牌
  • 专业的画册设计网站百度长尾关键词挖掘
  • 好的企业型网站模板交换友链是什么意思
  • 问卷调查微信小程序怎么做江门seo
  • 公司品牌网站建设价格糕点烘焙专业培训学校
  • 在百度上做网站seo服务是什么
  • b2c的平台有哪些谷歌搜索优化
  • 最便宜做公司网站广州网站开发多少钱
  • 网站制作 长沙b2b网站平台有哪些
  • 电商网站设计工作内容seo搜索引擎优化到底是什么
  • 成都网站建设推广投放广告的渠道有哪些
  • 厦门微信网站开发百度ai助手入口
  • b2c商城网站建设及运营方案网站推广的方式
  • 网站做ddns解析网站域名查询ip
  • 网业协同重庆企业网站排名优化
  • 中小企业的网站建设论文推广资源seo
  • wordpress插件 ftp银徽seo
  • 网站建设试题品牌推广策略怎么写
  • 私服网站空间seo整站优化费用
  • 【IntelliJ IDEA】如何在pom.xml中去除maven中未使用的依赖
  • ARM芯片架构之CoreSight SoC-400 组件介绍
  • 91、23种经典设计模式
  • 在Colab上复现LoRA相关论文实验的完整指南
  • 文字转语音 edge_tts
  • 重学React(五):脱围机制一