码迷,mamicode.com
首页 > 其他好文 > 详细

次小生成树模板

时间:2019-09-30 23:16:07      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:str   return   nio   次小生成树   集合   names   不用   print   string   

  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 }

 

次小生成树模板

标签:str   return   nio   次小生成树   集合   names   不用   print   string   

原文地址:https://www.cnblogs.com/pangbi/p/11614445.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!