acwing:1558. 加油站
加油站的建造位置必须使加油站与距离它最近的房屋的距离尽可能远。
与此同时,它还必须保证所有房屋都在其服务范围内。
现在,给出了城市地图和加油站的几个候选位置,请你提供最佳建议。
如果有多个解决方案,请输出选取位置与所有房屋的平均距离最小的解决方案。
如果这样的解决方案仍然不是唯一的,请输出选取位置编号最小的解决方案。
输入格式
第一行包含四个整数 N,房屋总数,M,加油站的候选位置总数,K,连接房屋或加油站的道路总数,Ds 加油站的最大服务范围。
所有房屋的编号从 1到 N,所有加油站侯选位置编号从
G1
到GM
。接下来 K 行,每行格式如下:
P1 P2 Dist
其中,
P1
和P2
表示一条 无向 道路连接的两个房屋或加油站侯选位置的编号,Dist
是道路长度,这是一个整数。输出格式
第一行输出所选位置的编号。
第二行输出加油站与距离其最近的房屋之间的距离以及与所有房屋之间的平均距离,精确到小数后一位。
如果解决方案不存在,则输出
No Solution
。
题解:
普通的dijkstra,但是注意精度(加1e-8才能过)。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1020, M = 20010;
typedef pair<int, int>PII;
int h[N], e[M], ne[M], w[M], idx;
int dis[N];
int n, m, k, ds;
bool st[N];
int sum[12];
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void dijk(int u)
{
memset(dis, 0x3f, sizeof(dis));
memset(st, false, sizeof(st));
priority_queue<PII, vector<PII>, greater<PII>>q;
q.push({ 0,u });
dis[u] = 0;
while (q.size()) {
auto t = q.top();
q.pop();
int v = t.second;
if (st[v]) {
continue;
}
st[v] = true;
for (int i = h[v];i != -1;i = ne[i]) {
int j = e[i];
if (dis[j] > dis[v] + w[i]) {
dis[j] = dis[v] + w[i];
q.push({ dis[j],j });
}
}
}
}
void solve()
{
memset(h, -1, sizeof(h));
cin >> n >> m >> k >> ds;
for (int i = 1;i <= k;i++) {
string s1, s2,s;
int a, b;
int c;
cin >> s1 >> s2 >> c;
if (s1[0] == 'G') {
s = s1.substr(1);
a = atoi(s.c_str()) + 1000;
}
else {
a = atoi(s1.c_str()) ;
}
if (s2[0] == 'G') {
s = s2.substr(1);
b = atoi(s.c_str()) + 1000;
}
else {
b = atoi(s2.c_str()) ;
}
add(a, b, c);
add(b, a, c);
}
bool Flag = 0;
string s_ans;
double av_ans = 0;
double ans = 0;
int th = 1;
int ht = 0;
do {
dijk(th + 1000);
/*for(int i=1;i<=n;i++){
printf("%d ",dis[i]);
}printf("\n");*/
bool flag = 0;
int anss = 5001;
int Sum = 0;
for (int i = 1;i <= n;i++) {
Sum += dis[i];
anss = min(anss, dis[i]);
if (dis[i] > ds) {
flag = 1;
break;
}
}
if (flag) {
continue;
}
sum[ht] = Sum;
ht++;
//printf("%d\n",sum[ht-1]);
if (ans < anss) {
ans = anss;
av_ans = (1.0) * sum[ht - 1] / n;
s_ans[0] = 'G', s_ans[1] = th + 48;
Flag = 1;
}
else if (ans == anss) {
if (av_ans > (1.0) * sum[ht - 1] / n) {
av_ans = (1.0) * sum[ht - 1] / n;
s_ans[0] = 'G', s_ans[1] = th + 48;
Flag = 1;
}
}
} while (th++, th <= m);
//av_ans=(av_ans+0.05)*10;
//av_ans/=10;
if (Flag) {
printf("%s\n", s_ans.c_str());
printf("%.1lf %.1lf", ans, av_ans + 1e-8);
}
else {
cout << "No Solution" << endl;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
while (t--) {
solve();
}
return 0;
}