求图的最小生成树。有两种方法。prim法和kruskal法。prim法只与节点有关,与边无关,所以适合于求边稠密的网的最小生成树。而kruskal算法与边有关,故其适合于求边比较稀疏的网络。
prim算法:
1)初始化set集为随意的一个节点,这里初始化为1。
2)找出与set集中的点相连的,花费最小的并且不再set集中的点,加入set集中。为了计算的方便,先将每个节点相连的所有边按权值升序排列。
3)直到所有的点都加到set集中,算法就停止了。
kruskal算法:
1)每次找权值最小的边,如果节点没有访问过,就加到set集中。如果访问过了,就合并两个set集。
2)这里为了剪去不必要的迭代,如果连通区域为1,并且所有的点都已经访问过了,就退出。
3)注意:不能排完序后从最小的加,因为不能确保为一棵树(可能生成环)。
1 //prim() 最小生成树
2 #include<iostream>
3 #include<cstring>
4 using namespace std;
5 int map[505][505], v, e;
6
7 int prim()
8 {
9 int sum = 0, road[505], i, j, k;
10 bool visit[505];
11 memset(visit, false, sizeof(visit));
12 for(i = 1; i <= v; ++i)
13 road[i] = map[1][i];
14 visit[1] = true;
15 for(i = 1; i < v; ++i)
16 {
17 int min = 1<<20;
18 for(j = i; j <= v; ++j)
19 if(!visit[j] && road[j] < min)
20 {
21 min = road[j];
22 k = j;
23 }
24 sum += road[k];
25 visit[k] = true;
26 for(j = 1; j <= v; ++j)
27 if(!visit[j] && road[j] > map[k][j]) //先将每个节点相连的所有边按权值升序排列
28 road[j] = map[k][j];
29 }
30 return sum;
31 }
32
33 int main()
34 {
35 // freopen("in.txt","r",stdin);
36 int n,i,a,b,c,w;
37 cin>>n;
38 while(n--)
39 {
40 memset(map,9999,sizeof(map));
41 cin>>v>>e;
42 for(i = 0; i < e; ++i)
43 {
44 cin>>a>>b>>c;
45 if(map[a][b])
46 map[a][b]=map[b][a] = c < map[a][b] ? c : map[a][b];
47 }
48 int min = 1<<30;
49 for(i = 0; i < v; ++i)
50 {
51 cin>>w;
52 if(min > w) min = w;
53 }
54 cout<<prim()+min<<endl;
55 }
56 return 0;
57 }
58
59
60
61 //kruskal()算法
62 #include<iostream>
63 #include<cstring>
64 #include<algorithm>
65 using namespace std;
66 int v,e,visit[505];
67
68 struct Node{
69 int a; int b; int c;
70 }map[505*505/2]; //注意:数组要开到 e 的大小
71
72 bool cmp(struct Node t1, struct Node t2)
73 {
74 return t1.c < t2.c;
75 }
76
77 int kruskal()
78 {
79 int sum = 0, k = 0, i, j, x, y, x1, y1;
80 i = 0;
81 while(k < v-1)
82 {
83 x = map[i].a; y = map[i].b;
84 x1 = visit[x]; y1 = visit[y];
85 if(x1 != y1)
86 {
87 ++k;
88 sum += map[i].c;
89 for(j = 1; j <= v; ++j) //并查集,不存在环
90 if(visit[j] == y1)
91 visit[j] = x1;
92 }
93 i++;
94 }
95 return sum;
96 }
97
98 int main()
99 {
100 // freopen("in.txt","r",stdin);
101 int n,i,w;
102 cin>>n;
103 while(n--)
104 {
105 cin>>v>>e;
106 for(i = 0; i < e; ++i)
107 cin>>map[i].a>>map[i].b>>map[i].c;
108 sort(map,map+e,cmp);
109 int min = 1<<30;
110 for(i = 1; i <= v; ++i)
111 {
112 visit[i] = i;
113 cin>>w;
114 if(min > w) min = w;
115 }
116 cout<<kruskal()+min<<endl;
117 }
118 return 0;
119 }
2 #include<iostream>
3 #include<cstring>
4 using namespace std;
5 int map[505][505], v, e;
6
7 int prim()
8 {
9 int sum = 0, road[505], i, j, k;
10 bool visit[505];
11 memset(visit, false, sizeof(visit));
12 for(i = 1; i <= v; ++i)
13 road[i] = map[1][i];
14 visit[1] = true;
15 for(i = 1; i < v; ++i)
16 {
17 int min = 1<<20;
18 for(j = i; j <= v; ++j)
19 if(!visit[j] && road[j] < min)
20 {
21 min = road[j];
22 k = j;
23 }
24 sum += road[k];
25 visit[k] = true;
26 for(j = 1; j <= v; ++j)
27 if(!visit[j] && road[j] > map[k][j]) //先将每个节点相连的所有边按权值升序排列
28 road[j] = map[k][j];
29 }
30 return sum;
31 }
32
33 int main()
34 {
35 // freopen("in.txt","r",stdin);
36 int n,i,a,b,c,w;
37 cin>>n;
38 while(n--)
39 {
40 memset(map,9999,sizeof(map));
41 cin>>v>>e;
42 for(i = 0; i < e; ++i)
43 {
44 cin>>a>>b>>c;
45 if(map[a][b])
46 map[a][b]=map[b][a] = c < map[a][b] ? c : map[a][b];
47 }
48 int min = 1<<30;
49 for(i = 0; i < v; ++i)
50 {
51 cin>>w;
52 if(min > w) min = w;
53 }
54 cout<<prim()+min<<endl;
55 }
56 return 0;
57 }
58
59
60
61 //kruskal()算法
62 #include<iostream>
63 #include<cstring>
64 #include<algorithm>
65 using namespace std;
66 int v,e,visit[505];
67
68 struct Node{
69 int a; int b; int c;
70 }map[505*505/2]; //注意:数组要开到 e 的大小
71
72 bool cmp(struct Node t1, struct Node t2)
73 {
74 return t1.c < t2.c;
75 }
76
77 int kruskal()
78 {
79 int sum = 0, k = 0, i, j, x, y, x1, y1;
80 i = 0;
81 while(k < v-1)
82 {
83 x = map[i].a; y = map[i].b;
84 x1 = visit[x]; y1 = visit[y];
85 if(x1 != y1)
86 {
87 ++k;
88 sum += map[i].c;
89 for(j = 1; j <= v; ++j) //并查集,不存在环
90 if(visit[j] == y1)
91 visit[j] = x1;
92 }
93 i++;
94 }
95 return sum;
96 }
97
98 int main()
99 {
100 // freopen("in.txt","r",stdin);
101 int n,i,w;
102 cin>>n;
103 while(n--)
104 {
105 cin>>v>>e;
106 for(i = 0; i < e; ++i)
107 cin>>map[i].a>>map[i].b>>map[i].c;
108 sort(map,map+e,cmp);
109 int min = 1<<30;
110 for(i = 1; i <= v; ++i)
111 {
112 visit[i] = i;
113 cin>>w;
114 if(min > w) min = w;
115 }
116 cout<<kruskal()+min<<endl;
117 }
118 return 0;
119 }