题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081
求一个最小生成树,再在这个最小生成树上删一条边,使得这条边两侧的人口数和与边长比值最大。用kruskal怎么写都写不出来,后来查了题解,prim会好一些:
求出最小生成树的同时记录最小生成树中任意两个点之间唯一路径的最大权的边的值,这个只要在要更新树的时候,在已经生成的树中更新就行了
AC代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 #include <queue> 7 #include <map> 8 #include <cmath> 9 #include <vector> 10 using namespace std; 11 #define N 1010 12 #define pi acos(-1.0) 13 #define inf 100000000 14 #define eps 1e-9 15 typedef long long ll; 16 typedef unsigned long long ull; 17 struct point{ 18 int x,y,v; 19 }p[N]; 20 double a[N][N],maxx[N][N],dis[N]; 21 int n,pre[N]; 22 bool vis[N]; 23 void prim(){ 24 double ans=0; 25 memset(vis,false,sizeof(vis)); 26 memset(maxx,0,sizeof(maxx)); 27 for(int i=1;i<=n;i++){ 28 dis[i]=a[1][i]; 29 pre[i]=1; 30 } 31 dis[1]=0; 32 vis[1]=true; 33 for(int i=1;i<n;i++){ 34 int k=0; 35 double tmp=inf; 36 for(int j=1;j<=n;j++){ 37 if(!vis[j]&&dis[j]<tmp){ 38 k=j; 39 tmp=dis[j]; 40 } 41 } 42 vis[k]=true; 43 ans+=tmp; 44 for(int j=1;j<=n;j++){ 45 if(!vis[j]&&dis[j]>a[k][j]){ 46 dis[j]=a[k][j]; 47 pre[j]=k; 48 } 49 } 50 for(int j=1;j<=n;j++){ 51 if(vis[j]&&j!=k){ 52 maxx[j][k]=max(maxx[j][pre[k]],tmp); 53 maxx[k][j]=maxx[j][k]; 54 } 55 } 56 } 57 double an=0; 58 for(int i=1;i<=n;i++){ 59 for(int j=1;j<=n;j++){ 60 if(i!=j){ 61 an=max(an,double(p[i].v+p[j].v)/(ans-maxx[i][j])); 62 } 63 } 64 } 65 printf("%.2f ",an); 66 } 67 68 int main(){ 69 int t; 70 // freopen("in","r",stdin); 71 scanf("%d",&t); 72 while(t--){ 73 scanf("%d",&n); 74 for(int i=1;i<=n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].v); 75 for(int i=1;i<=n;i++){ 76 for(int j=1;j<=n;j++){ 77 a[i][j]=sqrt(1.0*(p[i].x-p[j].x)*(p[i].x-p[j].x)+1.0*(p[i].y-p[j].y)*(p[i].y-p[j].y)); 78 } 79 } 80 prim(); 81 } 82 return 0; 83 }
WA代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef struct Node{ 23 int x; 24 int y; 25 double w; 26 }Node; 27 28 const int maxn = 1111; 29 int n, m, cnt; 30 int pre[maxn], vis[maxn], peo[maxn]; 31 int x[maxn], y[maxn], p[maxn]; 32 Node e[maxn<<4]; 33 double mst; 34 bool use[maxn<<4]; 35 36 bool cmp(Node n1, Node n2) { 37 return n1.w < n2.w; 38 } 39 40 inline void clear() { 41 memset(e, 0, sizeof(e)); 42 memset(x, 0, sizeof(x)); 43 memset(y, 0, sizeof(y)); 44 memset(p, 0, sizeof(p)); 45 memset(vis, 0, sizeof(vis)); 46 memset(use, 0, sizeof(use)); 47 memset(peo, 0, sizeof(peo)); 48 m = 0, cnt = 0, mst = 0; 49 } 50 51 inline void init() { 52 for(int i = 0; i < maxn; i++) pre[i] = i; 53 } 54 55 int find(int x) { 56 return x == pre[x] ? x : pre[x] = find(pre[x]); 57 } 58 59 bool unite(int x, int y) { 60 x = find(x); 61 y = find(y); 62 if(x != y) { 63 pre[x] = y; 64 return 1; 65 } 66 return 0; 67 } 68 69 double dis(int i, int j) { 70 return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); 71 } 72 73 int main() { 74 freopen("in", "r", stdin); 75 int T; 76 scanf("%d", &T); 77 while(T--) { 78 clear(); 79 scanf("%d", &n); 80 for(int i = 0; i < n; i++) { 81 scanf("%d %d %d", &x[i], &y[i], &p[i]); 82 } 83 for(int i = 0; i < n - 1; i++) { 84 for(int j = i + 1; j < n; j++) { 85 e[m].x = i; 86 e[m].y = j; 87 e[m++].w = dis(i, j); 88 } 89 } 90 init(); 91 sort(e, e+m, cmp); 92 for(int i = 0; i < m; i++) { 93 if(unite(e[i].x, e[i].y)) { 94 vis[cnt] = i; 95 mst += e[i].w; 96 peo[cnt] += p[e[i].x] + p[e[i].y]; 97 cnt++; 98 } 99 } 100 double ans = -1; 101 for(int i = 0; i < n; i++) { 102 for(int j = 0; j < n; j++) { 103 if(i != j) { 104 ans = max(ans, (p[i]+p[j]) / (mst-dis(i,j))); 105 } 106 } 107 } 108 printf("%.2lf ", ans); 109 } 110 return 0; 111 }
求出最小生成树的同时记录最小生成树中任意两个点之间唯一路径的最大权的边的值,这个只要在要更新树的时候,在已经生成的树中更新就行了