社区讨论

60分求助

P5304[GXOI/GZOI2019] 旅行者参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mlxcwu41
此快照首次捕获于
2026/02/22 14:18
2 周前
此快照最后确认于
2026/02/24 17:05
2 周前
查看原帖
CPP
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<ll, int> pli;
const int N = 100005;
const int M = 500005;
const ll INF = 1e18;

struct Edge {
    int to, nxt;
    ll w;
} e[M];

int head[N], cnt;
int n, m, k;
int a[N]; 
int from[M], to[M];
ll w[M];
ll dis[N];
bool vis[N];
ll ans;

void init() {
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void add(int u, int v, ll w) {
    e[cnt].to = v;
    e[cnt].w = w;
    e[cnt].nxt = head[u];
    head[u] = cnt ++;
}

void dijkstra(vector<int>& src) {
    priority_queue<pli, vector<pli>, greater<pli>> pq;
    for (int i = 1; i <= n; i++) {
        dis[i] = INF;
        vis[i] = false;
    }
    for (int x : src) {
        if (x != -1) {
            dis[x] = 0;
            pq.push({0, x});
        }
    }
    
    while (!pq.empty()) {
        int u = pq.top().second;
        pq.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (int i = head[u]; i != -1; i = e[i].nxt) {
            int v = e[i].to;
            if (dis[v] > dis[u] + e[i].w) {
                dis[v] = dis[u] + e[i].w;
                pq.push({dis[v], v});
            }
        }
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    
    // 读入边
    for (int i = 1; i <= m; i++) {
        scanf("%d%d%lld", &from[i], &to[i], &w[i]);
    }
    
    // 读入特殊点
    for (int i = 0; i < k; i++) {
        scanf("%d", &a[i]);
    }
    
    ans = INF;
    
    // 二进制分组
    for (int bit = 0; bit <= 20; bit ++) {
        init();
        for (int i = 1; i <= m; i++) add(from[i], to[i], w[i]);
        
        vector<int> src;
        for (int i = 0; i < k; i ++) {
            if (!(i >> bit & 1)) src.push_back(a[i]);
            else src.push_back(-1);
        }
        dijkstra(src);
        
        for (int i = 0; i < k; i ++) {
            if ((i >> bit & 1) && dis[a[i]] < ans) {
                ans = min(ans, dis[a[i]]);
            }
        }
        
        init();
        for (int i = 1; i <= m; i ++) add(to[i], from[i], w[i]);
        
        src.clear();
        for (int i = 0; i < k; i ++) {
            if ((i >> bit & 1)) src.push_back(a[i]);
            else src.push_back(-1);
        }
        dijkstra(src);
        
        for (int i = 0; i < k; i ++) {
            if (!(i >> bit & 1) && dis[a[i]] < ans) {
                ans = min(ans, dis[a[i]]);
            }
        }
    }
    
    printf("%lld\n", ans);
}

int main() {
    int T;
    scanf("%d", &T);
    while (T --) {
        solve();
    }
    return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...