(1)问题描述:
政府建公路把所有城市联系起来,使得公路最长的边最短,输出这个最长的边。
(2)基本思路:
使得公路最长的边最短其实就是要求最小生成树。
(3)代码实现:
普里姆算法:
#include <iostream>
using namespace std;
#define MAX_DIS 1000000
int main()
{
int T;
cin >> T;
for(int t = 1; t <= T; t++)
{
int n;
cin >> n;
int mat[n + 1][n + 1];
int d[n + 1];
int v[n + 1];
for(int i = 1; i <= n; i++)
{
fill(mat[i], mat[i] + n + 1, MAX_DIS);
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
cin >> mat[i][j];
}
}
int max_length = 0;
fill(d, d + n + 1, MAX_DIS);
fill(v, v + n + 1, 0);
d[1] = 0;
for(int i = 1; i <= n; i++)
{
int min = MAX_DIS;
int min_index = -1;
for(int j = 1; j <= n; j++)
{
if(d[j] < min && v[j] == 0)
{
min = d[j];
min_index = j;
}
}
//加入点min_index
v[min_index] = 1;
if(min > max_length)
max_length = min;
for(int j = 1; j <= n; j++)
{
if(v[j] == 0 && mat[min_index][j] < d[j])
{
d[j] = mat[min_index][j];
}
}
}
cout << max_length << endl;
if(t != T)
cout << endl;
}
return 0;
}
克鲁斯卡尔算法:
#include <iostream>
#include <algorithm>
using namespace std;
int u[200000];//左端点
int v[200000];//右端点
int w[200000];//权重
int e[200000];//辅助排序,排完序后,e[0]所存的值是使得权重w[e[0]]最小的
int p[501];//并查集
bool cmp(int i, int j)
{
return w[i] < w[j];
}
int find(int x)
{
return (p[x] == -1)? x: p[x] = find(p[x]);
}
int _union(int x, int y)
{
p[y] = x;
}
int main()
{
int T;
cin >> T;
for(int t = 1; t <= T; t++)
{
int n;
cin >> n;
int count = 0;//表示一共有几条边
int weight;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
cin >> weight;
if(weight != 0)
{
if(i < j)//只需要存其中一条边
{
u[count] = i;
v[count] = j;
w[count] = weight;
count++;
}
}
}
}
//思想:把边排序
for(int i = 0; i < count; i++)
e[i] = i;
sort(e, e + count, cmp);
//并查集初始化每个点的根结点为自己(-1)
for(int i = 1; i <= n; i++)
p[i] = -1;
int min_w_index;
int x;
int y;
int edge = 0;
for(int i = 0; i < count; i++)
{
min_w_index = e[i];
x = find(u[min_w_index]);
y = find(v[min_w_index]);
//若左端点和右端点的根结点一样,则加入的边必然导致环
if(find(x) != find(y))//根结点不同的时候加入
{
edge++;
_union(x, y);
}
if(edge == n - 1)
{
cout << w[min_w_index] << endl;
break;
}
}
if(t != T)
cout << endl;
}
}