原题链接:洛谷P5304 [GXOI/GZOI2019]旅行者

洛谷P5304 [GXOI/GZOI2019]旅行者

洛谷P5304 [GXOI/GZOI2019]旅行者

洛谷P5304 [GXOI/GZOI2019]旅行者

题解

题意:在一个无向图中指定k个点,求这k个点中两两最短路长度的最小值

算法:dijkstra+合并点+二进制

1.暴力

对于每一个指定点,跑k次dijkstra,暴力比较最小值,复杂度O(N2logM)。

for(int i=1;i<=K;i++){
    dijkstra(spe[i]);
    for(int j=1;j<=K;j++)
        if(j!=i&&dis[spe[j]]<ans)
            ans=dis[spe[j]];
}

 

完整代码,50opt:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAXN = 1e5 + 7, MAXM = 1e6 + 50;
 5 const LL INF = 1e17 + 7;
 6 int head[MAXN], sz, nxt[MAXM], len[MAXM], to[MAXM];
 7 inline void add(int x, int y, LL z) {
 8     nxt[++sz] = head[x];
 9     head[x] = sz;
10     to[sz] = y;
11     len[sz] = z;
12     nxt[++sz] = head[y];
13     head[y] = sz;
14     to[sz] = y;
15     len[sz] = z;
16 }
17 LL dis[MAXN], ans;
18 int spe[MAXN] /*special point*/, is[MAXN] /*is special*/;
19 bool vis[MAXN];
20 inline void dijkstra(int S) {
21     memset(dis, 0x3f, sizeof(dis));
22     memset(vis, 0, sizeof(vis));
23     priority_queue<pair<LL, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
24     pq.push(make_pair(0, S));
25     while (pq.size()) {
26         pair<LL, int> cur = pq.top();
27         pq.pop();
28         int idx = cur.second;
29         LL dist = cur.first;
30         if (vis[idx] || dis[idx] < dist)
31             continue;
32         vis[idx] = 1;
33         for (int i = head[idx]; i; i = nxt[i])
34             if (!vis[to[i]] && dist + len[i] < dis[to[i]]) {
35                 dis[to[i]] = dist + len[i];
36                 pq.push(make_pair(dis[to[i]], to[i]));
37             }
38     }
39 }
40 int Case, N, M, K;
41 int main() {
42     scanf("%d", &Case);
43     while (Case--) {
44         scanf("%d%d%d", &N, &M, &K);
45         sz = 0;
46         memset(head, 0, sizeof(head));
47         for (int i = 1; i <= M; i++) {
48             int ii, jj;
49             LL kk;
50             scanf("%d%d%lld", &ii, &jj, &kk);
51             add(ii, jj, kk);
52         }
53         memset(is, 0, sizeof(is));
54         for (int i = 1; i <= K; i++) {
55             scanf("%d", spe + i);
56             is[spe[i]] = 1;
57         }
58         ans = INF;
59         for (int i = 1; i <= K; i++) {
60             dijkstra(spe[i]);
61             for (int j = 1; j <= K; j++)
62                 if (j != i && dis[spe[j]] < ans)
63                     ans = dis[spe[j]];
64         }
65         printf("%lld\n", ans);
66     }
67     return 0;
68 }
View Code

相关文章: