大白的345 頁。 題目:秦始皇要修一個道路的工程,使得所有城市全部聯通。 然後道士徐福可以幫他修一條不需勞動力的路。 給出兩個變量: 讓這條路的起終點的人口和A 除以除此之外的路的勞動力之和B 秦始皇想讓這條路修的位置,使得A/B 最大 思路: 用最小生成樹首先生成一個全通圖 再用DFS算出每一個城市之間唯一路徑上的最大的權值的路 然後枚舉每一個城市,用最小生成樹計算出的SUM - maxcost[U][V]
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #define INF 0x3f3f3f3f #define MAX(a,b) a>b?a:b using namespace std; struct point { int x,y,p; }P[1005]; int set[1005]; struct line { int s,e; double w; bool operator < (const line &cmp)const { return w<cmp.w; } }L[1005*1005]; double maxcost[1005][1005]; double map[1005][1005]; vector<int>minmap[1005]; bool vis[1005]; int find(int x) { while(set[x]!=x) x=set[x]; return x; } double dis(point tx,point ty) { return sqrt((double)(tx.x-ty.x)*(tx.x-ty.x)+(double)(tx.y-ty.y)*(tx.y-ty.y)); } void dfs(int st,int pos) { for(int i=0;i<minmap[pos].size();i++) { if(!vis[minmap[pos][i]]) { vis[minmap[pos][i]]=true; maxcost[st][minmap[pos][i]]=MAX(maxcost[st][pos],map[pos][minmap[pos][i]]); // printf("maxcost[%d][%d]=%.4lf\n",st,minmap[pos][i],maxcost[st][minmap[pos][i]]); dfs(st,minmap[pos][i]); } } } int main() { int T; scanf("%d",&T); while(T--) { int n; memset(maxcost,0,sizeof(maxcost)); scanf("%d",&n); int top=0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].p); for(int j=1;j<i;j++) { L[top].s=i; L[top].e=j; L[top].w=dis(P[i],P[j]); map[i][j]=map[j][i]=L[top++].w; } minmap[i].clear(); set[i]=i; } sort(L,L+top); double sum=0; for(int i=0;i<top;i++) { int xx=find(L[i].s); int yy=find(L[i].e); if(xx!=yy) { set[xx]=yy; sum+=L[i].w; minmap[L[i].s].push_back(L[i].e); minmap[L[i].e].push_back(L[i].s); } } //printf("sum = %.4lf\n",sum); for(int i=1;i<=n;i++) { memset(vis,false,sizeof(vis)); dfs(i,i); maxcost[i][i]=0; } double ans=0; for(int i=1;i<n;i++) { for(int j=i+1;j<=n;j++) { int tmp=P[i].p+P[j].p; double tt=1.0*tmp/(sum-maxcost[i][j]); if(tt>ans)ans=tt; } } printf("%.2lf\n",ans); } return 0; }