社区讨论
dij,为什么只有10分,玄关
P14318「ALFR Round 11」B 行走 (walk)参与者 3已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mhizw6j1
- 此快照首次捕获于
- 2025/11/03 18:26 4 个月前
- 此快照最后确认于
- 2025/11/03 18:26 4 个月前
CPP
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <iomanip>
using namespace std;
typedef long long ll;
const double INF = 1e18;
const double EPS = 1e-12;
struct Edge {
double to, rev;
Edge(double t, double r) : to(t), rev(r) {}
};
// Dijkstra算法计算最短时间
vector<double> dijkstra(double start, double end, const vector<vector<Edge>>& graph,
const vector<double>& weights) {
double n = graph.size();
vector<double> dist(n, INF);
dist[start] = 0;
priority_queue<pair<double, double>, vector<pair<double, double>>, greater<>> pq;
pq.emplace(0, start);
while (!pq.empty()) {
auto [cost, u] = pq.top();
pq.pop();
if (u == end) break;
if (cost > dist[u] + EPS) continue;
for (const Edge& e : graph[u]) {
double v = e.to;
double idx = e.rev;
double time = 1.0 / weights[idx];
if (dist[v] > dist[u] + time + EPS) {
dist[v] = dist[u] + time;
pq.emplace(dist[v], v);
}
}
}
return dist;
}
// 找到最短路径上的边
vector<double> get_path_edges(double start, double end, const vector<vector<Edge>>& graph,
const vector<double>& weights) {
double n = graph.size();
vector<double> dist(n, INF);
vector<double> prev(n, -1);
vector<double> prev_edge(n, -1);
dist[start] = 0;
priority_queue<pair<double, double>, vector<pair<double, double>>, greater<>> pq;
pq.emplace(0, start);
while (!pq.empty()) {
auto [cost, u] = pq.top();
pq.pop();
if (u == end) break;
if (cost > dist[u] + EPS) continue;
for (const Edge& e : graph[u]) {
double v = e.to;
double idx = e.rev;
double time = 1.0 / weights[idx];
if (dist[v] > dist[u] + time + EPS) {
dist[v] = dist[u] + time;
prev[v] = u;
prev_edge[v] = idx;
pq.emplace(dist[v], v);
}
}
}
vector<double> path;
for (double v = end; v != start && v != -1; v = prev[v]) {
if (prev_edge[v] != -1) {
path.push_back(prev_edge[v]);
}
}
return path;
}
double solve() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
double n, m, k;
cin >> n >> m >> k;
vector<vector<Edge>> graph(n + 1); // 1-based
vector<pair<double, double>> edges(m);
for (double i = 0; i < m; i++) {
double u, v;
cin >> u >> v;
edges[i] = {u, v};
graph[u].emplace_back(v, i);
graph[v].emplace_back(u, i);
}
double x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
// 初始权重都是1
vector<double> base_weights(m, 1);
// 检查可达性
vector<double> distA_base = dijkstra(x1, y1, graph, base_weights);
vector<double> distB_base = dijkstra(x2, y2, graph, base_weights);
if (distA_base[y1] >= INF - EPS || distB_base[y2] >= INF - EPS) {
return -1;
}
// 获取原始最短路径的边
vector<double> pathA = get_path_edges(x1, y1, graph, base_weights);
vector<double> pathB = get_path_edges(x2, y2, graph, base_weights);
// 找出公共边(冲突边)
unordered_set<double> setA(pathA.begin(), pathA.end());
unordered_set<double> common_edges;
for (double e : pathB) {
if (setA.count(e)) {
common_edges.insert(e);
}
}
double c = common_edges.size();
// 优化策略:优先升级冲突边,剩余的平均分配
double k1 = min(k, c); // 用于冲突边的升级数
double remaining_k = k - k1;
// 计算升级后的权重
vector<double> weights(m, 1);
// 先升级冲突边
for (double e : common_edges) {
if (k1 <= 0) break;
weights[e] += 1;
k1--;
}
// 剩余的平均分配给所有边
double add_all = remaining_k / m;
double rem = (int)remaining_k % (int)m;
for (double i = 0; i < m; i++) {
weights[i] += add_all;
}
for (double i = 0; i < rem; i++) {
weights[i] += 1;
}
// 计算优化后的时间
vector<double> distA_opt = dijkstra(x1, y1, graph, weights);
vector<double> distB_opt = dijkstra(x2, y2, graph, weights);
if (distA_opt[y1] >= INF - EPS || distB_opt[y2] >= INF - EPS) {
return -1;
}
return distA_opt[y1] + distB_opt[y2];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cout << fixed << setprecision(12);
double T;
cin >> T;
while (T--) {
double res = solve();
if (res < 0) {
cout << "-1\n";
} else {
cout << res << "\n";
}
}
return 0;
}
以为是dij板子+时间分配,但是只对k=0的情况
record
回复
共 2 条回复,欢迎继续交流。
正在加载回复...