題目鏈接 原標題:Qin Shi Huang’s National Road System CSDN把System設置成非法字符?
題意
NN N 個城市每個城市有一定的人口,秦始皇要修地鐵了。他的手下運用魔法之后可以讓一條路的代價為0,秦始皇想知道在那條路上運用魔法可以使得這條路兩端的人口總數修路的花費\frac{這條路兩端的人口總數}{修路的花費} 修 路 的 花 費 這 條 路 兩 端 的 人 口 總 數 ? 最大
思路
先求最小生成樹然后判斷每條邊,如果這條邊是最小生成樹上的邊 ans = 最小生數的權值和?這條邊這條邊兩端人口總和\frac{最小生數的權值和-這條邊}{這條邊兩端人口總和} 這 條 邊 兩 端 人 口 總 和 最 小 生 數 的 權 值 和 ? 這 條 邊 ? , 如果這條邊不是最小生成樹上的一條邊,我們需要構造一個次小生成樹,然后類似的求出最大值,中間不斷更新MaxMax M a x 即可。
kruskal:kruskal: k r u s k a l : 218MS 32720K ,空間勉強卡過,vectorvector v e c t o r 的內存成倍擴大。。 prim:prim: p r i m : 124MS 10268K 29061190 2019-04-26 11:45:53 Accepted 4081 2420 B G++ henuyh
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn
= 1001 ;
const int inf
= 0x3f3f3f3f ;
const int mod
= 1e9 + 7 ;
using namespace std
;
int n
, m
;
struct ac
{ int u
, v
, w
; ac ( int u_
= 0 , int v_
= 0 , int w_
= 0 ) { u
= u_
; v
= v_
; w
= w_
; } inline int Dis ( ac x
) { return ( ( x
. u
- u
) * ( x
. u
- u
) + ( x
. v
- v
) * ( x
. v
- v
) ) ; }
} ;
int g
[ maxn
] [ maxn
] , val
[ maxn
] , vis
[ maxn
] , dis
[ maxn
] ;
int pre
[ maxn
] , maxd
[ maxn
] [ maxn
] ;
bool used
[ maxn
] [ maxn
] ; double Count ( int i
, int j
, double sum
) { return ( val
[ i
] + val
[ j
] ) * 1.0 / ( sum
- sqrt ( g
[ i
] [ j
] ) ) ;
}
void prim ( int s
) { mem ( maxd
, 0 ) ; mem ( vis
, 0 ) ; mem ( used
, 0 ) ; for ( int i
= 0 ; i
< n
; ++ i
) { dis
[ i
] = g
[ s
] [ i
] ; pre
[ i
] = s
; } vis
[ s
] = 1 ; double sum
= 0 ; for ( int i
= 1 ; i
< n
; ++ i
) { int u
= - 1 , MIN
= inf
; for ( int j
= 0 ; j
< n
; ++ j
) { if ( vis
[ j
] ) continue ; if ( MIN
> dis
[ j
] ) { MIN
= dis
[ j
] ; u
= j
; } } if ( u
== - 1 ) break ; vis
[ u
] = 1 ; sum
+ = sqrt ( MIN
) ; used
[ pre
[ u
] ] [ u
] = used
[ u
] [ pre
[ u
] ] = 1 ; maxd
[ u
] [ pre
[ u
] ] = maxd
[ pre
[ u
] ] [ u
] = MIN
; for ( int j
= 0 ; j
< n
; ++ j
) { if ( j
== u
) continue ; if ( vis
[ j
] ) { maxd
[ u
] [ j
] = maxd
[ j
] [ u
] = max ( maxd
[ pre
[ u
] ] [ j
] , MIN
) ; } if ( vis
[ j
] == 0 && dis
[ j
] > g
[ u
] [ j
] ) { dis
[ j
] = g
[ u
] [ j
] ; pre
[ j
] = u
; } } } double ans
= 0 ; for ( int i
= 0 ; i
< n
; ++ i
) { for ( int j
= i
+ 1 ; j
< n
; ++ j
) { if ( used
[ i
] [ j
] ) ans
= max ( ans
, Count ( i
, j
, sum
) ) ; else ans
= max ( ans
, Count ( i
, j
, sum
- sqrt ( maxd
[ i
] [ j
] ) + sqrt ( g
[ i
] [ j
] ) ) ) ; } } printf ( "%.2lf\n" , ans
) ;
} int main ( ) { ios
:: sync_with_stdio ( false ) ; cin
. tie ( 0 ) ; cout
. tie ( 0 ) ; int T
; scanf ( "%d" , & T
) ; while ( T
-- ) { scanf ( "%d" , & n
) ; vector
< ac
> t ( n
) ; mem ( g
, inf
) ; for ( int i
= 0 ; i
< n
; ++ i
) { scanf ( "%d%d%d" , & t
[ i
] . u
, & t
[ i
] . v
, & val
[ i
] ) ; } for ( int i
= 0 ; i
< n
; ++ i
) { for ( int j
= i
+ 1 ; j
< n
; ++ j
) { g
[ i
] [ j
] = g
[ j
] [ i
] = t
[ i
] . Dis ( t
[ j
] ) ; } } prim ( 0 ) ; } return 0 ;
}
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn
= 1e3 + 1 ;
const int inf
= 0x3f3f3f3f ;
const int mod
= 1e9 + 7 ;
using namespace std
;
struct ac
{ int u
, v
, flag
; double w
; ac ( int u_
= 0 , int v_
= 0 , double w_
= 0 , int flag_
= 0 ) { u
= u_
; v
= v_
; w
= w_
; flag
= flag_
; } bool operator < ( ac t
) { return w
< t
. w
; }
} g
[ 1000001 ] ;
vector
< int > son
[ maxn
] ;
int pre
[ maxn
] , val
[ maxn
] ;
double dis
[ maxn
] [ maxn
] ;
int find
( int x
) { return ( pre
[ x
] == x
) ? x
: pre
[ x
] = find ( pre
[ x
] ) ;
}
int n
, m
;
double Dis ( ac x
, ac y
) { return sqrt ( ( x
. u
- y
. u
) * ( x
. u
- y
. u
) + ( x
. v
- y
. v
) * ( x
. v
- y
. v
) ) ;
}
double Count ( double all
, ac t
) { return ( val
[ t
. u
] + val
[ t
. v
] ) * 1.0 / ( all
- t
. w
) ;
}
void Kruskal ( ) { for ( int i
= 0 ; i
<= n
; ++ i
) { son
[ i
] . clear ( ) ; son
[ i
] . push_back ( i
) ; pre
[ i
] = i
; } sort ( g
, g
+ m
) ; double sum
= 0 ; int cnt
= 0 ; for ( int i
= 0 ; i
< m
; ++ i
) { if ( cnt
== n
+ 1 ) break ; int fx
= find ( g
[ i
] . u
) ; int fy
= find ( g
[ i
] . v
) ; if ( fx
== fy
) continue ; g
[ i
] . flag
= 1 ; sum
+ = g
[ i
] . w
; cnt
++ ; int lenx
= son
[ fx
] . size ( ) ; int leny
= son
[ fy
] . size ( ) ; if ( lenx
< leny
) { swap ( lenx
, leny
) ; swap ( fx
, fy
) ; } for ( int j
= 0 ; j
< lenx
; ++ j
) { for ( int k
= 0 ; k
< leny
; ++ k
) { dis
[ son
[ fx
] [ j
] ] [ son
[ fy
] [ k
] ] = dis
[ son
[ fy
] [ k
] ] [ son
[ fx
] [ j
] ] = g
[ i
] . w
; } } pre
[ fy
] = fx
; for ( int j
= 0 ; j
< leny
; ++ j
) { son
[ fx
] . push_back ( son
[ fy
] [ j
] ) ; } son
[ fy
] . clear ( ) ; } double ans
= - 1 ; for ( int i
= 0 ; i
< m
; ++ i
) { if ( g
[ i
] . flag
) { ans
= max ( ans
, Count ( sum
, g
[ i
] ) ) ; } else { ans
= max ( ans
, Count ( sum
+ g
[ i
] . w
- dis
[ g
[ i
] . u
] [ g
[ i
] . v
] , g
[ i
] ) ) ; } } printf ( "%.2lf\n" , ans
) ;
} int main ( ) { ios
:: sync_with_stdio ( false ) ; cin
. tie ( 0 ) ; cout
. tie ( 0 ) ; int T
; scanf ( "%d" , & T
) ; while ( T
-- ) { scanf ( "%d" , & n
) ; vector
< ac
> t ( n
) ; for ( int i
= 0 ; i
< n
; ++ i
) { scanf ( "%d%d%d" , & t
[ i
] . u
, & t
[ i
] . v
, & val
[ i
] ) ; } m
= 0 ; for ( int i
= 0 ; i
< n
; ++ i
) { for ( int j
= i
+ 1 ; j
< n
; ++ j
) { g
[ m
++ ] = ac ( i
, j
, Dis ( t
[ i
] , t
[ j
] ) , 0 ) ; } } Kruskal ( ) ; } return 0 ;
}
總結
以上是生活随笔 為你收集整理的HDU-4081 Qin Shi Huang's Road 8ystem(次小生成树) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。