HDU4756+Prim

题意简单:去掉最小生成树的某一条边并补上一条,求MaxVal

思路:贪心(借鉴Yamidie的思路。。。)

分别求出最小生成树和次最小生成树,再在这两棵树上求最小生成树

 

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 #include<math.h>
  6 using namespace std;
  7 const int maxn = 1015;
  8 const int maxm = maxn*maxn;
  9 const int inf1 = 0x3f3f3f3f;
 10 const double inf2 = 9999999999;
 11 
 12 struct Point {
 13     double x,y;
 14 }pnt[ maxn ];
 15 struct Edge{
 16     int u,v;
 17     double val;
 18     int id;
 19 }edge[ maxn<<1 ];
 20 int cnt_edge;
 21 double mat[ maxn ][ maxn ];
 22 double dis[ maxn ];
 23 bool vis[ maxn ];
 24 int pre[ maxn ];
 25 
 26 double LenPrim1;
 27 double LenPrim2;
 28 
 29 int fa[ maxn ],rank[ maxn ];
 30 
 31 int find( int x ){
 32     if( x==fa[x] ) return x;
 33     else return fa[ x ] = find( fa[x] );
 34 }
 35 
 36 void init( int n ){
 37     for( int i=0;i<n;i++ ){
 38         fa[ i ] = i;
 39         rank[ i ] = 1;
 40     }
 41     return ;
 42 } 
 43  
 44 double dist( int i,int j ){
 45     return sqrt( (pnt[i].x-pnt[j].x)*(pnt[i].x-pnt[j].x)+(pnt[i].y-pnt[j].y)*(pnt[i].y-pnt[j].y) );
 46 } 
 47 
 48 int cmp( Edge a,Edge b ){
 49     return a.val<b.val;
 50 }    
 51 
 52 void GetMap( int n ){
 53     for( int i=0;i<n;i++ )
 54         for( int j=0;j<n;j++ ){
 55             mat[i][j] = dist( i,j );
 56             //printf("mat[%d][%d]=%.3lf\n",i,j,mat[i][j]);
 57         }
 58     return ;
 59 }
 60 
 61 double prim( int n,int Belong ){
 62     for( int i=0;i<n;i++ ){
 63         dis[ i ] = mat[0][i];
 64         vis[ i ] = false;
 65         pre[ i ] = 0;
 66     }
 67     vis[0] = true;
 68     //if( Belong==2 ){
 69     //    for( int i=0;i<n;i++ )for( int j=0;j<n;j++ ) 
 70             //printf("mat[%d][%d]=%.3lf\n",i,j,mat[i][j]);
 71     //}
 72     double ans = 0;
 73     for( int i=0;i<n;i++ ){
 74         int id = -1;
 75         double M = inf2;
 76         for( int j=0;j<n;j++ ){
 77             if( !vis[j] && M>dis[j] ){
 78                 M = dis[j];
 79                 id = j;
 80             }
 81         }
 82         if( id==-1 ) break;
 83         vis[ id ] = true;
 84         ans += M;
 85         edge[ cnt_edge ].u = pre[ id ];
 86         edge[ cnt_edge ].v = id;
 87         edge[ cnt_edge ].id = Belong;
 88         edge[ cnt_edge ].val = mat[ id ][ pre[id] ];
 89         //printf("u = %d,v = %d\n",edge[cnt_edge].u,edge[cnt_edge].v);
 90         cnt_edge ++ ;
 91         for( int j=0;j<n;j++ ){
 92             if( !vis[j] && dis[j]>mat[id][j] ){
 93                 dis[j] = mat[id][j];
 94                 pre[ j ] = id;
 95             }
 96         }
 97     }
 98     return ans;
 99 }    
100 
101 void Deal( int n ){
102     for( int i=0;i<cnt_edge;i++ ){
103         mat[ edge[i].u ][ edge[i].v ] = inf2;
104         mat[ edge[i].v ][ edge[i].u ] = inf2;
105     }
106 }
107 
108 double Kruskal( int n,int id ){
109     double ans = 0;
110     init( n );
111     int cnt = 0;
112     for( int i=0;i<cnt_edge;i++ ){
113         if( i==id ) continue;
114         int fx = find( edge[i].u );
115         int fy = find( edge[i].v );
116         if( fx!=fy ){
117             if( rank[ fx ]<rank[ fy ] ){
118                 rank[ fy ] += rank[ fx ];
119                 fa[ fx ] = fy;
120             }
121             else {
122                 rank[ fx ] += rank[ fy ];
123                 fa[ fy ] = fx;
124             }
125             cnt ++ ;
126             ans += edge[i].val;
127             if( cnt==n-1 ) break;
128         }
129        }
130        return ans;
131 }
132 
133 int main(){
134     int T;
135     scanf("%d",&T);
136     while( T-- ){
137         int n;
138         double k;
139         scanf("%d%lf",&n,&k);
140         for( int i=0;i<n;i++ )
141             scanf("%lf%lf",&pnt[i].x,&pnt[i].y);
142         GetMap( n );
143         cnt_edge = 0;
144         LenPrim1 = prim( n,1 );
145         Deal( n );
146         LenPrim2 = prim( n,2 );
147         double ans = LenPrim1;
148         double temp_ans = 0;
149         sort( edge,edge+cnt_edge,cmp );
150         //printf("cnt_edge = %d\n",cnt_edge);
151         for( int i=0;i<cnt_edge;i++ ){
152             if( edge[i].id==1 && edge[i].u!=0 && edge[i].v!=0 ){
153                 temp_ans = Kruskal( n,i );
154                 if( temp_ans>ans )
155                     ans = temp_ans;
156             }
157         }
158         printf("%.2lf\n",ans*k);
159     }
160     return 0;
161 }
View Code

 

posted @ 2013-09-25 00:09  xxx0624  阅读(301)  评论(0编辑  收藏  举报