http://acm.hdu.edu.cn/showproblem.php?pid=4081
题目大意:在一个完全图中找一棵生成树,满足其中一条边的两个邻接点的点权之和除以该生成树的所有比安全和的比例最大,求该比例。
设最终所要的比例为ratio,则初始是设ratio为一个小负数。首先计算出图的最小生成树,设最小生成树的总长度为ans;然后枚举所有的点对(i,j),如果边(i,j)在最小生成树中,则比较 ratio 和 (cost[i]+cost[j])/(ans -G[i][j]) 的大小,否则,比较 ratio 和 (cost[i]+cost[j])/(ans -path[i][j]) 的大小;其中path[i][j]表示当最小生成树中加入了一条边(i,j)后,则形成了一个环,于是必须要在环中删除一条最长的非(i,j)的边,path[i][j]记录的就是这条边。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const int N = 1010; double G[N][N],minCost[N],x[N],y[N],path[N][N],cost[N],ratio; int pre[N] , vis[N] , n; bool used[N][N]; double prim() { double ans = 0; memset(vis,0,sizeof(vis)); memset(used,0,sizeof(used)); memset(path,0,sizeof(path)); vis[1] = 1; for(int i=1;i<=n;i++) { minCost[i] = G[1][i]; pre[i] = 1; } while(1) { int u = -1; for(int i=1;i<=n;i++) if(!vis[i] && (u==-1 || minCost[i]<minCost[u])) u = i; if(u == -1) break; used[pre[u]][u] = used[u][pre[u]] = 1; ans += G[pre[u]][u]; vis[u] = 1; for(int i=1;i<=n;i++) { if(vis[i] && i != u) path[u][i]=path[i][u]=max(path[i][pre[u]] , minCost[u]); if(!vis[i]) { if(minCost[i] > G[u][i]) { minCost[i] = G[u][i]; pre[i] = u; } } } } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf%lf%lf",x+i,y+i,cost+i); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) G[i][j] = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); double ans = prim(); ratio = -1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i != j) if(used[i][j]) checkmax(ratio,(cost[i]+cost[j])/(ans-G[i][j])); else checkmax(ratio,(cost[i]+cost[j])/(ans-path[i][j])); printf("%.2lf\n" , ratio); } return 0; }