HDU4756+Prim
题意简单:去掉最小生成树的某一条边并补上一条,求MaxVal
思路:贪心(借鉴Yamidie的思路。。。)
分别求出最小生成树和次最小生成树,再在这两棵树上求最小生成树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
keep moving...