次小生成树模板
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]