刚接触的次小生成树,就是最小生成树通过一次变换得到。
o(N^3)的做法:
求得最小生成树,标记其中的边,枚举删除每条边,再求最小生成树,并在这些权值中取得最小值,得到次小生成树。
o(N^2)的做法:
先求得最小生成树,并在此中标记每条边是否用过。
mmax[I][J],数组来记录I到J最小生成树路径上权值的一条最大值。
接着枚举不在最小生成树的边(I,J);
SecMst=Mst-edge[I][J]+mmax[I][J],取最小值,为次小生成树的值
Hdu 4081
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 #define INF 0xfffffff 9 double edge[1001][1001]; 10 double mmax[1001][1001]; 11 double lowcost[1001]; 12 int nearvex[1001]; 13 int used[1001][1001]; 14 bool vis[1001]; 15 int t,n; 16 struct Node 17 { 18 int u,v,w; 19 }fpoint[1001]; 20 21 double cal(Node a,Node b) 22 { 23 return sqrt(1.0*((a.u-b.u)*(a.u-b.u)+(a.v-b.v)*(a.v-b.v))); 24 } 25 26 double prim(int u0) 27 { 28 memset(vis,0,sizeof(vis)); 29 memset(nearvex,0xff,sizeof(nearvex)); 30 int i,j; 31 for(i=1;i<=n;i++) 32 { 33 lowcost[i]=INF; 34 } 35 lowcost[u0]=0; 36 double sumweight=0; 37 for(i=1;i<=n;i++) 38 { 39 int mmin=INF; 40 int v=-1; 41 for(j=1;j<=n;j++) 42 { 43 if(vis[j]!=1&&lowcost[j]<mmin) 44 { 45 v=j; 46 mmin=lowcost[j]; 47 } 48 } 49 for(j=1;j<=n;j++) 50 { 51 if(vis[j]&&j!=v) 52 { 53 mmax[j][v]=mmax[v][j]=(mmax[j][nearvex[v]]>edge[nearvex[v]][v]?mmax[j][nearvex[v]]:edge[nearvex[v]][v]); 54 } 55 } 56 if(nearvex[v]!=-1) //表示该段已用 57 { 58 used[nearvex[v]][v]=used[v][nearvex[v]]=2; 59 } 60 vis[v]=1; //表示该点已经记录 61 sumweight+=lowcost[v]; 62 for(j=1;j<=n;j++) 63 { 64 if(edge[v][j]!=0&&!vis[j]&&edge[v][j]<lowcost[j]) //更新lowcost数组,找到下一条合适的边 65 { 66 nearvex[j]=v; 67 lowcost[j]=edge[v][j]; 68 } 69 } 70 } 71 return sumweight; 72 } 73 74 int main() 75 { 76 scanf("%d",&t); 77 while(t--) 78 { 79 scanf("%d",&n); 80 int i,j; 81 for(i=1;i<=n;i++) 82 { 83 int x,y,w; 84 scanf("%d%d%d",&x,&y,&w); 85 fpoint[i].u=x,fpoint[i].v=y,fpoint[i].w=w; 86 } 87 for(i=1;i<=n;i++) 88 { 89 for(j=1;j<=n;j++) 90 { 91 edge[i][j]=0; 92 } 93 } 94 for(i=1;i<=n;i++) 95 { 96 for(j=i+1;j<=n;j++) 97 { 98 used[i][j]=used[j][i]=1; 99 edge[i][j]=edge[j][i]=cal(fpoint[i],fpoint[j]); 100 } 101 } 102 int u0=1; 103 double ans=prim(u0); 104 double r=-1; 105 for(i=1;i<=n;i++) 106 { 107 for(j=1;j<=n;j++) 108 { 109 if(used[i][j]==2) 110 { 111 r=r>(fpoint[i].w+fpoint[j].w)/(ans-edge[i][j])?r:(fpoint[i].w+fpoint[j].w)/(ans-edge[i][j]); 112 } 113 else 114 if(used[i][j]==1) 115 { 116 r=r>(fpoint[i].w+fpoint[j].w)/(ans-mmax[i][j])?r:(fpoint[i].w+fpoint[j].w)/(ans-mmax[i][j]); 117 } 118 } 119 } 120 printf("%0.2lf ",r); 121 } 122 return 0; 123 }