社区讨论

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 条回复,欢迎继续交流。

正在加载回复...