次小生成树HDU--4081

刚接触的次小生成树,就是最小生成树通过一次变换得到。

o(N^3)的做法:

  求得最小生成树,标记其中的边,枚举删除每条边,再求最小生成树,并在这些权值中取得最小值,得到次小生成树。

o(N^2)的做法:

  先求得最小生成树,并在此中标记每条边是否用过。

  mmax[I][J],数组来记录I到J最小生成树路径上权值的一条最大值。

  接着枚举不在最小生成树的边(I,J);

  SecMst=Mst-edge[I][J]+mmax[I][J],取最小值,为次小生成树的值

 

     Hdu 4081

  

  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\n",r);
121     }
122     return 0;
123 }
View Code

 

posted on 2013-07-16 09:30  张狂不年轻°  阅读(247)  评论(0)    收藏  举报