【题目描述】
农夫约翰被选为他们镇的镇长!
他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。
约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。
约翰的农场的编号是
1
1
1,其他农场的编号是
2
∼
n
2∼n
2∼n。
为了使花费最少,他希望用于连接所有的农场的光纤总长度尽可能短。
你将得到一份各农场之间连接距离的列表,你必须找出能连接所有农场并使所用光纤最短的方案。
【输入格式】
第一行包含一个整数
n
n
n,表示农场个数。
接下来
n
n
n行,每行包含
n
n
n个整数,输入一个对角线上全是
0
0
0的对称矩阵。
其中第
x
+
1
x+1
x+1行
y
y
y列的整数表示连接农场
x
x
x和农场
y
y
y所需要的光纤长度。
【输出格式】
输出一个整数,表示所需的最小光纤长度。
【数据范围】
3
≤
n
≤
100
3≤n≤100
3≤n≤100
每两个农场间的距离均是非负整数且不超过
100000
100000
100000。
【输入样例】
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0
【输出样例】
28
【分析】
模板题,当做复习一下Prim算法~
【代码】
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 110; int g[N][N]; int st[N], dis[N]; int n; int prim() { memset(dis, 0x3f, sizeof dis); dis[1] = 0; int res = 0; for (int i = 0; i < n; i++) { int t = -1; for (int j = 1; j <= n; j++) if (!st[j] && (!~t || dis[j] < dis[t])) t = j; res += dis[t]; st[t] = 1; for (int j = 1; j <= n; j++) dis[j] = min(dis[j], g[t][j]); } return res; } int main() { cin >> n; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) cin >> g[i][j]; cout << prim() << endl; return 0; }
【题目描述】
某个局域网内有
n
n
n台计算机和
k
k
k条 双向 网线,计算机的编号是
1
∼
n
1∼n
1∼n。由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。
注意:
因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用 f ( i , j ) f(i,j) f(i,j)表示 i , j i,j i,j之间连接的畅通程度, f ( i , j ) f(i,j) f(i,j)值越小表示 i , j i,j i,j之间连接越通畅。
现在我们需要解决回路问题,我们将除去一些连线,使得网络中没有回路且不影响连通性(即如果之前某两个点是连通的,去完之后也必须是连通的),并且被除去网线的 Σ f ( i , j ) Σf(i,j) Σf(i,j)最大,请求出这个最大值。
【输入格式】
第一行两个正整数
n
,
k
n,k
n,k。
接下来的
k
k
k行每行三个正整数
i
,
j
,
m
i,j,m
i,j,m表示
i
,
j
i,j
i,j两台计算机之间有网线联通,通畅程度为
m
m
m。
【输出格式】
一个正整数,表示被除去网线的
Σ
f
(
i
,
j
)
Σf(i,j)
Σf(i,j)的最大值。
【数据范围】
1
≤
n
≤
100
1≤n≤100
1≤n≤100
0
≤
k
≤
200
0≤k≤200
0≤k≤200
1
≤
f
(
i
,
j
)
≤
1000
1≤f(i,j)≤1000
1≤f(i,j)≤1000
【输入样例】
5 5 1 2 8 1 3 1 1 5 3 2 4 5 3 4 2
【输出样例】
8
【分析】
本题可能存在多个连通块,需要我们去掉权值尽可能大的边,且不影响每个连通块内各点的连通性。即需要求出最小的“生成森林”。我们在做Kruskal算法时,当某条边的两个端点已经被连通时,说明该边需要去除,将 r e s res res加上这条边的权值即可。
【代码】
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 110, M = 210; int pre[N]; int n, m; struct Edge { int x, y, w; bool operator< (const Edge& t) const { return w < t.w; } }e[M]; int find(int k) { if (pre[k] == k) return k; return pre[k] = find(pre[k]); } int kruskal() { sort(e, e + m); int res = 0; for (int i = 0; i < m; i++) { int px = find(e[i].x), py = find(e[i].y); if (px != py) pre[px] = py;//x与y不在一个连通块中则连接 else res += e[i].w;//x与y已经连通了说明这条边需要去掉 } return res; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) pre[i] = i; for (int i = 0; i < m; i++) cin >> e[i].x >> e[i].y >> e[i].w; cout << kruskal() << endl; return 0; }