次小生成树模板

Posted pangbi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了次小生成树模板相关的知识,希望对你有一定的参考价值。

  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 

 

以上是关于次小生成树模板的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P4180 模板严格次小生成树[BJWC2010]

P4180 模板严格次小生成树[BJWC2010]

模板 次小生成树

「LuoguP4180」 模板严格次小生成树[BJWC2010](倍增 LCA Kruscal

次小生成树模板

cogs P1578模板 次小生成树初级练习题