定义
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得 w(T) 最小,则此 T 为 G 的最小生成树。
最小生成树其实是最小权重生成树的简称。
解决问题
要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。
模板
#include<iostream>
#include<fstream>
using namespace std;
#define MAX 100
#define MAXCOST 0x7fffffff
int graph[MAX][MAX];
int prim(int graph[][MAX], int n)
{
int lowcost[MAX];
int mst[MAX];
int i, j, min, minid, sum = 0;
for (i = 2; i <= n; i++)
{
lowcost[i] = graph[1][i];
mst[i] = 1;
}
mst[1] = 0;
for (i = 2; i <= n; i++)
{
min = MAXCOST;
minid = 0;
for (j = 2; j <= n; j++)
{
if (lowcost[j] < min && lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
cout << "V" << mst[minid] << "-V" << minid << "=" << min << endl;
sum += min;
lowcost[minid] = 0;
for (j = 2; j <= n; j++)
{
if (graph[minid][j] < lowcost[j])
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
return sum;
}
int main()
{
int i, j, k, m, n;
int x, y, cost;
ifstream in("input.txt");
in >> m >> n;
for (i = 1; i <= m; i++)
{
for (j = 1; j <= m; j++)
{
graph[i][j] = MAXCOST;
}
}
for (k = 1; k <= n; k++)
{
in >> i >> j >> cost;
graph[i][j] = cost;
graph[j][i] = cost;
}
cost = prim(graph, m);
cout << "最小权值和=" << cost << endl;
system("pause");
return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,tot=0,k=0;
int fat[200010];
struct node
{
int from,to,dis;
}edge[200010];
bool cmp(const node &a,const node &b)
{
return a.dis<b.dis;
}
int father(int x)
{
if(fat[x]!=x)
return father(fat[x]);
else return x;
}
void unionn(int x,int y)
{
fat[father(y)]=father(x);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].dis);
}
for(int i=1;i<=n;i++) fat[i]=i;
sort(edge+1,edge+1+m,cmp);
for(int i=1;i<=m;i++)
{
if(k==n-1) break;
if(father(edge[i].from)!=father(edge[i].to))
{
unionn(edge[i].from,edge[i].to);
tot+=edge[i].dis;
k++;
}
}
printf("%d",tot);
return 0;
}
例题
由题意可得,这是一道最小生成树题也是一道模板题
#include <iosteam>
using namespace std;
const int N = 5000100;
int n, m, cnt, fa[N], sum;
double ans;
struct Node {
int x, y;
}E[N];
struct node {
int from, to;
double w;
}e[N];
int read() {
int s = 0, w = 1;
char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') w = -1;ch = getchar();}
while(isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
return s * w;
}
void add(int x, int y, double z) {
e[++cnt].from =x;
e[cnt].to = y;
e[cnt].w = z;
}
double jl(int x, int y) {
return (double)(sqrt((double)(E[x].x - E[y].x) * (E[x].x - E[y].x) + (double)(E[x].y - E[y].y) * (E[x].y - E[y].y)));
}
bool cmp(node x, node y) {
if(x.w == y.w) return x.from < y.from;
return x.w < y.w;
}
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; i++)
E[i].x = read(), E[i].y = read();
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
double z = jl(i, j);
add(i, j, z);
}
}
for(int i = 1; i <= m; i++) {
int x = read(), y = read();
add(x, y, 0.0);
}
sort(e + 1, e + 1 + cnt, cmp);
for(int i = 1; i <= cnt; i++) {
int fx = find(e[i].from), fy = find(e[i].to);
if(fx != fy) {
fa[fx] = fy;
sum++;
ans += e[i].w;
}
if(sum == n - 1) break;
}
printf("%.2lf
", ans);
return 0;
}