1 kruskal
2 #include <vector>
3 #include <iostream>
4 #include <cstdio>
5 #include <cstring>
6 #include <algorithm>
7 #define INF 0x3f3f3f3f
8
9 using namespace std;
10 int n,m;
11 struct data
12 {
13 int u,v,w;
14 bool vis;
15 } p[20010];
16 vector<int>G[110];
17 int per[110],maxd[110][110];
18 bool cmp(data a,data b)
19 {
20 return a.w < b.w;
21 }
22 int Union_Find(int x)
23 {
24 return x == per[x] ? x: per[x] = Union_Find(per[x]);
25 }
26 void kruskal()
27 {
28 sort(p,p+m,cmp);
29 for(int i=0; i<=n; i++)//初始化
30 {
31 G[i].clear();
32 G[i].push_back(i);
33 per[i]=i;
34 }
35 int sum=0,k=0;//sum是最小生成树的值
36 for(int i=0; i<m; i++){
37 if(k==n-1) break;
38 int x1=Union_Find(p[i].u),x2=Union_Find(p[i].v);
39 if(x1!=x2){
40 k++;
41 p[i].vis=1;//这条边已经用过了
42 sum+=p[i].w;
43 int len_x1=G[x1].size();
44 int len_x2=G[x2].size();
45 for(int j=0; j<len_x1; j++) //更新两点之间距离的最大值
46 for(int k=0; k<len_x2; k++)
47 maxd[G[x1][j]][G[x2][k]]=maxd[G[x2][k]][G[x1][j]]=p[i].w;//因为后面的边会越来越大,所以这里可以直接等于当前边的长度
48 per[x1]=x2;
49 //因为per[x1] = x2,在Union_Find函数中要寻找和x1相关联节点的跟节点的时候,都会找到x2,所以这里不用再去更新和x1节点相连的节点
50 //十分感谢Self-Discipline博主,提出此问题
51 // int tem[110];
52 // for(int j=0; j<len_x2; j++)//现在已经属于一棵树了,那么我们就将点添加到相应的集合中
53 // tem[j]=G[x2][j];
54 for(int j=0; j<len_x1; j++)
55 G[x2].push_back(G[x1][j]);
56 // for(int j=0; j<len_x2; j++)
57 // G[x1].push_back(tem[j]);
58 }
59 }
60 int cisum=INF;//次小生成树的权值
61 for(int i=0; i<m; i++)
62 if(!p[i].vis)
63 cisum=min(cisum,sum+p[i].w-maxd[p[i].u][p[i].v]);
64 if(cisum>sum)
65 printf("%d\n",sum);
66 else
67 printf("Not Unique!\n");
68 }
69 int main()
70 {
71 int T;
72 scanf("%d\n",&T);
73 while(T--){
74 scanf("%d%d",&n,&m);
75 for(int i=0; i<m; i++){
76 scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w);
77 p[i].vis = false;
78 }
79 kruskal();
80 }
81 return 0;
82 }
83
84 prim
85 #include<iostream>
86 #include<string>
87 #include<cstdio>
88 #include<map>
89 #include<cstring>
90 #include<cmath>
91 #include<algorithm>
92 using namespace std;
93 const int INF=99999999;
94 const int N=1010;
95 struct point
96 {
97 int x,y;
98 } p[N];
99 double G[N][N],dist[N];
100 double path[N][N];//从i到j的路径上最大边的权值
101 int population[N];//每个城市的人口数
102 int pre[N],visit[N];
103 bool used[N][N];//边是否在该MST中
104 int n;
105 inline double Dist(point v1,point v2)
106 {
107 return sqrt(double(v1.x-v2.x)*(v1.x-v2.x)+double(v1.y-v2.y)*(v1.y-v2.y));
108 }
109 double Prim()
110 {
111 double Mst=0;
112 memset(visit,0,sizeof(visit));
113 memset(used,0,sizeof(used));
114 memset(path,0,sizeof(path));
115 visit[1]=1;
116 for(int i=1; i<=n; ++i){
117 dist[i] = G[1][i];
118 pre[i] = 1;
119 }
120 for(int i=1; i<n; ++i){
121 int u=-1;
122 for(int j=1; j<=n; ++j){
123 if(!visit[j]){
124 if(u==-1||dist[j]<dist[u])
125 u=j;
126 }
127 }
128 used[u][pre[u]]=used[pre[u]][u] = true;//加入MST
129 Mst+=G[pre[u]][u];
130 visit[u]=1;
131 for(int j=1; j<=n; ++j){
132 if(visit[j]&&j!=u)//求从u到j的路径上最大边的权值
133 {
134 path[u][j]=path[j][u]=max(path[j][pre[u]],dist[u]);
135 //printf("path[j][pre[u]]:%lf\n",path[j][pre[u]]);
136 }
137 if(!visit[j]){
138 if(dist[j]>G[u][j])//更新相邻顶点的dist
139 {
140 dist[j]=G[u][j];
141 pre[j]=u;
142 }
143 }
144 }
145 }
146 return Mst;
147 }
148 int main()
149 {
150 int tcase;
151 scanf("%d",&tcase);
152 while(tcase--){
153 scanf("%d",&n);
154 memset(G,0,sizeof(G));
155 for(int i=1; i<=n; ++i)
156 scanf("%d%d%d",&p[i].x,&p[i].y,&population[i]);
157 for(int i=1; i<=n; ++i){
158 for(int j=1; j<=n; ++j){
159 if(i!=j)
160 G[i][j]=Dist(p[i],p[j]);
161 }
162 }
163 double Mst=Prim();
164 double res=-1;
165 for(int i=1; i<=n; ++i){
166 for(int j=1; j<=n; ++j)
167 if(i!=j){
168 if(used[i][j])
169 res=max(res,(population[i]+population[j])/(Mst-G[i][j]));
170 else
171 res=max(res,(population[i]+population[j])/(Mst-path[i][j]));
172 }
173 }
174 printf("%.2f\n",res);
175 }
176 return 0;
177 }