这是一个要建图和枚举的题目 ,
想到枚举 , 我们这个题目只能枚举人口 A, 和 最后所得的最短路B , 进一步想 , 最短路B要枚举是不可能的 , 所以只能枚举人口A , 也就是枚举每一条边(假设这条边的边权为0) 。
想到这里题目就基本上做出来了,有几个注意点:
1、求最短路时用kruskal算法 , 不然会超时 , (一般情况下都是kruskal这个算法更快 , 因为它可以通过优先队列来进行优化)。
2、两个城市之间的距离是指它们的最小距离 , 也就是两个城市相连的那条直线。
代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct node
{
int from , to ;
double dist;
node(int from , int to , double dist)
{
this->from = from;
this->to = to;
this->dist = dist;
}
bool operator <(const struct node &ans) const
{
return dist > ans.dist;
}
};
const int MAXN = 1100 ;
int city[MAXN][3] ;
int n , done[MAXN] , p[MAXN] , f[MAXN];
double maxbian[MAXN][MAXN] , sum = 0 ;
priority_queueedge;
void init()
{
int i;
scanf("%d", &n);
memset(maxbian , 0 , sizeof(maxbian));
for(i = 1; i <= n; i++)
{
scanf("%d %d %d", &city[i][0], &city[i][1], &city[i][2]);
f[i] = i;
}
for(i = 1; i <= n; i++)
for(int j = i+1; j <= n; j++)
{
double xx = city[i][0] - city[j][0];
double yy = city[i][1] - city[j][1];
double zz = sqrt(xx*xx+yy*yy);
maxbian[i][j] = maxbian[j][i] = zz;
edge.push(node(i , j , zz));
//
cout<<maxbian[i][j]<<endl;
}
sum = 0;
}
int find(int x)
{
int y = x;
while(x != f[x])
x = f[x];
while(y != x)
{
int xy = f[y];
f[y] = x;
y =xy;
}
return x;
}
void mintree()
{
int bz =0 ;
vectorq[MAXN];
while(!edge.empty())
{
struct node s = edge.top();
edge.pop();
int x = find(s.from) , y = find(s.to);
if(x != y)
{
maxbian[s.from][s.to] = maxbian[s.to][s.from] = s.dist;
sum += s.dist;
f[y] = x;
bz += 1;
q[s.from].push_back(s.to);
q[s.to].push_back(s.from);
}
if(bz == n-1)
break;
}
memset(done , 0 , sizeof(done));
done[1] = 1;
queuesq ;
sq.push(1);
while(!sq.empty())
{
int u_bian = sq.front(); sq.pop();
for(int i =0 ; i < q[u_bian].size() ; i++)
{
int zy = q[u_bian][i];//cout<<u_bian<<zy<<endl;
if(done[zy])
continue ;
p[zy] = u_bian;
done[zy] = 1;
sq.push(zy);
}
}
}
void dfs(int v)
{
for ( int u = 1; u <= n; ++u )
//这里还可以用邻接表来减少时间
{
if(!done[u] && p[u] == v)
{
done[u] = 1;
for ( int x = 1; x <= n; ++x )
if (done[x] && x != u )
{
maxbian[x][u] = maxbian[u][x] =
maxbian[x][v]>maxbian[u][v]?maxbian[x][v]:maxbian[u][v];
}
dfs(u);
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int i , j;
init();
mintree();
double xy = 0;
memset(done , 0, sizeof(done));
done[1] = 1 ;
dfs(1);
//for(i =1 ; i <= n; i++)
//
for(j = i+1 ; j <= n; j++)
//
cout<<maxbian[i][j]<<endl;
for(i = 1; i <= n; i++)
{
for(j = i+1; j <= n; j++)
{
//cout<<sum<<","<<maxbian[i][j]<<endl;
if((double)(city[i][2]+city[j][2])/(sum-maxbian[i][j]) > xy)
xy = (double)(city[i][2]+city[j][2])/(sum-maxbian[i][j]);
}
}
printf("%.2lf\n" , xy);
}
return 0;
}
想到枚举 , 我们这个题目只能枚举人口 A, 和 最后所得的最短路B , 进一步想 , 最短路B要枚举是不可能的 , 所以只能枚举人口A , 也就是枚举每一条边(假设这条边的边权为0) 。
想到这里题目就基本上做出来了,有几个注意点:
1、求最短路时用kruskal算法 , 不然会超时 , (一般情况下都是kruskal这个算法更快 , 因为它可以通过优先队列来进行优化)。
2、两个城市之间的距离是指它们的最小距离 , 也就是两个城市相连的那条直线。
代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct node
{
};
const int MAXN = 1100 ;
int city[MAXN][3] ;
int n , done[MAXN] , p[MAXN] , f[MAXN];
double maxbian[MAXN][MAXN] , sum = 0 ;
priority_queueedge;
void init()
{
}
int find(int x)
{
}
void mintree()
{
}
void dfs(int v)
{
}
int main()
{
}