ACM 实验室2020.10.03天梯赛练习*1
7-13 垃圾箱分布
题意:n个点,m个能当作起始点,k条边,起始点不能与n个点距离超过ds,求到n个点的最短距离最长的起始点
思路:跑m遍dijkstra即可,练习的时候时间不够没写完
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int maxn = 1000 + 15;
const double eps = 1e-9;
int n, m, k, ds;
vector<PII> v[maxn];
int dis[maxn];
bool vis[maxn];
priority_queue<PII, vector<PII>, greater<> > que;
int dijkstra(int x) {
memset(vis, false, sizeof(vis));
memset(dis, 0x3f, sizeof dis);
dis[x] = 0;
que.push(PII(0, x));
while (!que.empty()) {
int point = que.top().second;
que.pop();
if (vis[point])
continue;
vis[point] = true;
for (auto i:v[point]) {
if (dis[i.first] > dis[point] + i.second) {
dis[i.first] = dis[point] + i.second;
que.push(PII(dis[i.first], i.first));
}
}
}
int minn = 0x3f3f3f3f;
for (int i = 1; i <= n; i++) {
if (dis[i] > ds)
return 0x3f3f3f3f;
minn = min(minn, dis[i]);
}
return minn;
}
int main() {
cin >> n >> m >> k >> ds;
getchar();
for (int i = 0; i < k; i++) {
char s;
int a = 0, b = 0, c;
scanf("%c", &s);
if (s == 'G') {
cin >> a;
a += 1000;
getchar();
} else {
while (s != ' ') {
a *= 10;
a += s - '0';
scanf("%c", &s);
}
}
scanf("%c", &s);
if (s == 'G') {
cin >> b;
b += 1000;
getchar();
} else {
while (s != ' ') {
b *= 10;
b += s - '0';
scanf("%c", &s);
}
}
cin >> c;
getchar();
v[a].push_back(PII(b, c));
v[b].push_back(PII(a, c));
}
int point = 0;
int ansmin = -1;
int ansavg = 0x3f3f3f3f;
for (int i = 1001; i <= 1000 + m; i++) {
double minn = dijkstra(i);
if (minn == 0x3f3f3f3f)
continue;
if (ansmin < minn) {
ansmin = minn;
int avg = 0;
for (int j = 1; j <= n; j++)
avg += dis[j];
ansavg = avg;
point = i;
} else if (minn == ansmin) {
int avg = 0;
for (int j = 1; j <= n; j++)
avg += dis[j];
if (ansavg > avg) {
ansavg = avg;
point = i;
}
}
}
if (point != 0) {
cout << "G" << point - 1000 << endl;
printf("%.1lf %.1lf\n", ansmin * 1.0, ansavg / (double) n);
} else
cout << "No Solution" << endl;
return 0;
}
7-15 地铁一日游
题意:n个点m段线路k为为计费距离限制,给m段线路后,q次询问,每次从x站出发,求能拍照的站点
思路:题目吧啦了一堆,无非是要说以下条件:
选某个车费中最远的(比如说,我花5块钱能到3个地方,那么选最远的)
路线的端点(注意!这里是指连通路线的端点)
用Floyed求最短路,每个站点都找到能拍照的站点,对每次查询都dfs一遍。
靠蒙和猜题意,慢慢写
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int maxn = 200 + 5;
const double eps = 1e-9;
struct point {
int vis = 0;
int ends = 0;
vector<int> res;
} points[maxn];
int n, m, k;
int mp[maxn][maxn];
void floyed() {
for (int K = 1; K <= n; K++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j && mp[i][j] > mp[i][K] + mp[K][j])
mp[i][j] = mp[i][K] + mp[K][j];
}
void dfs(int x, int vis) {
for (int i = 0; i < points[x].res.size(); i++) {
int tmp = points[x].res[i];
if (points[tmp].vis != vis) {
points[tmp].vis = vis;
dfs(tmp, vis);
}
}
}
int main() {
memset(mp, 0x3f, sizeof mp);
cin >> n >> m >> k;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u;
points[u].ends = 1;
do {
cin >> w >> v;
if (w < mp[u][v]) {
mp[u][v] = w;
mp[v][u] = w;
}
u = v;
} while (getchar() != '\n');
points[u].ends = 1;
}
floyed();
for (int i = 1; i <= n; i++) {
map<int, int> mp1;
for (int j = 1; j <= n; j++)
if (mp[i][j] != 0x3f3f3f3f && mp[i][j] > mp1[mp[i][j] / k + 2])
mp1[mp[i][j] / k + 2] = mp[i][j];
for (int j = 1; j <= n; j++)
if (mp[i][j] == mp1[mp[i][j] / k + 2] || (i != j && mp[i][j] != 0x3f3f3f3f && points[j].ends == 1))
points[i].res.push_back(j);
}
int q;
cin >> q;
for (int i = 1; i <= q; i++) {
int start;
cin >> start;
points[start].vis = i;
dfs(start, i);
int first = true;
for (int j = 1; j <= n; j++)
if (points[j].vis == i) {
if (!first)
cout << " ";
first = false;
cout << j;
}
cout << endl;
}
return 0;
}

浙公网安备 33010602011771号