
本文共 3264 字,大约阅读时间需要 10 分钟。
Prim / Kruskal - 局域网 - 洛谷 P2820
某个局域网内有 n 台计算机和 k 条 双向 网线,计算机的编号是 1∼n。由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。
注意:
对于某一个连接,虽然它是双向的,但我们不将其当做回路。本题中所描述的回路至少要包含两条不同的连接。
两台计算机之间最多只会存在一条连接。不存在一条连接,它所连接的两端是同一台计算机。
因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用 f(i,j) 表示 i,j 之间连接的畅通程度,f(i,j) 值越小表示 i,j 之间连接越通畅。
现在我们需要解决回路问题,我们将除去一些连线,使得网络中没有回路且不影响连通性(即如果之前某两个点是连通的,去完之后也必须是连通的),并且被除去网线的 Σf(i,j) 最大,请求出这个最大值。
输入格式
第一行两个正整数 n,k。
接下来的 k 行每行三个正整数 i,j,m 表示 i,j 两台计算机之间有网线联通,通畅程度为 m。
输出格式
一个正整数,表示被除去网线的 Σf(i,j) 的最大值。
数据范围
1 ≤ n ≤ 100 , 0 ≤ k ≤ 200 , 1 ≤ f ( i , j ) ≤ 1000 1≤n≤100, 0≤k≤200, 1≤f(i,j)≤1000 1≤n≤100,0≤k≤200,1≤f(i,j)≤1000
输入样例:
5 51 2 81 3 11 5 32 4 53 4 2
输出样例:
8
分析:
根 据 题 意 : 给 定 一 个 包 含 多 个 连 通 块 的 图 , 要 从 每 个 连 通 块 中 去 除 几 条 边 。 根据题意:给定一个包含多个连通块的图,要从每个连通块中去除几条边。 根据题意:给定一个包含多个连通块的图,要从每个连通块中去除几条边。
要 求 : 去 除 几 条 边 后 , 每 个 连 通 块 中 的 点 的 数 量 不 变 , 换 言 之 , 不 改 变 任 何 两 点 之 间 的 连 通 性 。 要求:去除几条边后,每个连通块中的点的数量不变,换言之,不改变任何两点之间的连通性。 要求:去除几条边后,每个连通块中的点的数量不变,换言之,不改变任何两点之间的连通性。
要 求 去 除 掉 的 所 有 边 的 权 值 之 和 的 最 大 值 。 要求去除掉的所有边的权值之和的最大值。 要求去除掉的所有边的权值之和的最大值。
等 价 于 求 , 将 所 有 连 通 块 变 成 最 小 生 成 树 后 , 需 要 去 掉 的 边 的 权 值 之 和 。 等价于求,将所有连通块变成最小生成树后,需要去掉的边的权值之和。 等价于求,将所有连通块变成最小生成树后,需要去掉的边的权值之和。
解 决 方 案 : 解决方案: 解决方案:
① 、 P r i m 算 法 : 逐 个 向 集 合 中 添 加 到 连 通 块 距 离 最 短 的 点 , 直 到 剩 下 的 点 与 当 前 连 通 块 不 连 通 。 ①、Prim算法:逐个向集合中添加到连通块距离最短的点,直到剩下的点与当前连通块不连通。 ①、Prim算法:逐个向集合中添加到连通块距离最短的点,直到剩下的点与当前连通块不连通。
当 剩 下 的 点 都 不 连 通 时 , 会 默 认 选 择 一 个 未 被 标 记 过 的 点 t , 接 着 更 新 与 t 相 邻 的 点 的 距 离 , 计 算 新 的 连 通 块 。 \qquad当剩下的点都不连通时,会默认选择一个未被标记过的点t,接着更新与t相邻的点的距离,计算新的连通块。 当剩下的点都不连通时,会默认选择一个未被标记过的点t,接着更新与t相邻的点的距离,计算新的连通块。
这 样 , 我 们 先 累 加 输 入 的 所 有 边 的 权 值 总 和 t o t , 再 对 所 有 连 通 块 求 最 小 生 成 树 , 代 价 r e s , 输 出 t o t − r e s 。 \qquad这样,我们先累加输入的所有边的权值总和tot,再对所有连通块求最小生成树,代价res,输出tot-res。 这样,我们先累加输入的所有边的权值总和tot,再对所有连通块求最小生成树,代价res,输出tot−res。
注 意 , 只 有 当 连 通 的 时 候 我 们 才 累 加 到 各 连 通 块 最 小 生 成 树 的 总 代 价 中 , 即 d i s [ j ] ≠ i n f 时 , 才 累 加 。 \qquad注意,只有当连通的时候我们才累加到各连通块最小生成树的总代价中,即dis[j]≠inf时,才累加。 注意,只有当连通的时候我们才累加到各连通块最小生成树的总代价中,即dis[j]=inf时,才累加。
② 、 K r u s k a l 算 法 : 方 便 用 于 处 理 多 个 连 通 块 的 最 小 生 成 树 。 ②、Kruskal算法:方便用于处理多个连通块的最小生成树。 ②、Kruskal算法:方便用于处理多个连通块的最小生成树。
但 是 注 意 , 要 求 去 除 的 边 的 权 值 之 和 , 故 我 们 要 累 加 被 舍 弃 掉 的 边 的 权 值 。 \qquad但是注意,要求去除的边的权值之和,故我们要累加被舍弃掉的边的权值。 但是注意,要求去除的边的权值之和,故我们要累加被舍弃掉的边的权值。
代码:
Prim算法:
#include#include #include #include using namespace std;const int N=110, inf=0x3f3f3f3f;int n,m,g[N][N],dis[N];bool st[N];int prim(){ memset(dis,0x3f,sizeof dis); dis[1]=0; int res=0; for(int i=0;i dis[j])) t=j; if(dis[t]!=inf) res+=dis[t]; st[t]=true; for(int j=1;j<=n;j++) dis[j]=min(dis[j],g[t][j]); } return res;}int main(){ scanf("%d%d",&n,&m); memset(g,0x3f,sizeof g); int a,b,c,tot=0; for(int i=0;i
Kruskal算法:
#include#include #include using namespace std;const int N=210;int n,m;int p[N];struct edge{ int u,v,w; bool operator < (const edge &t) const { return w >n>>m; for(int i=0;i >E[i].u>>E[i].v>>E[i].w; for(int i=1;i<=n;i++) p[i]=i; int res=kruskal(); cout< <
发表评论
最新留言
关于作者
