2017年多校賽第九場 1006 Senior Pan(dijkstra套路題)
阿新 • • 發佈:2018-12-24
這道題有很多解法,我是按照題解的做法寫了一遍。
題意:給出一個有向圖,然後有k個點,問這k個點兩兩之間的最短距離的最小值是多少。
解法:題解是把k個點按照每個點二進位制位的不同分成兩個集合,然後求一次多源最短路。由於最大的數是1e5,所以也就到個。。。2^17的樣子?由於是有向圖,還需要正反都跑一遍。所以一共跑34次最短路就出來了。。。
程式碼如下:
#include<iostream> #include<cstdio> #include<vector> #include<queue> #include<utility> #include<stack> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<map> using namespace std; typedef pair<long long, int> pii; const int maxn = 1e5 + 5; const int maxm = 2e5 + 5; const long long INF = 1e18; int a[maxn]; int head[maxn], to[maxm], nx[maxm], cost[maxm], ppp = 0; void add_edge(int u, int v, int val) { to[ppp] = v, nx[ppp] = head[u], cost[ppp] = val, head[u] = ppp++; } priority_queue <pii, vector<pii>, greater<pii> > q; long long dis[maxn]; void dijkstra() { while(!q.empty()) { pii tmp = q.top(); q.pop(); int u = tmp.second; if(dis[u] < tmp.first) continue; for(int i = head[u]; ~i; i = nx[i]) { int v = to[i]; if(dis[v] > dis[u] + cost[i]) { dis[v] = dis[u] + cost[i]; q.push(pii(dis[v], v)); } } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif int T, Case = 1; scanf("%d", &T); while(T--) { memset(head, -1, sizeof(head)); ppp = 0; int n, m; scanf("%d%d", &n, &m); while(m--) { int u, v, c; scanf("%d%d%d", &u, &v, &c); add_edge(u, v, c); } int k; scanf("%d", &k); for(int i = 0; i < k; i++) { scanf("%d", &a[i]); } int ind = 1; long long Min = 1e18; while(1) { int cnt = 0; fill(dis, dis + n + 1, INF); for(int i = 0; i < k; i++) { if(a[i] & ind) { dis[a[i]] = 0; q.push(pii(0, a[i])); cnt++; } } if(cnt == 0) break; dijkstra(); for(int i = 0; i < k; i++) { if(a[i] & ind) continue; if(Min > dis[a[i]]) Min = dis[a[i]]; } fill(dis, dis + n + 1, INF); for(int i = 0; i < k; i++) { if(!(a[i] & ind)) { dis[a[i]] = 0; q.push(pii(0, a[i])); cnt++; } } dijkstra(); for(int i = 0; i < k; i++) { if(!(a[i] & ind)) continue; if(Min > dis[a[i]]) Min = dis[a[i]]; } ind <<= 1; } printf("Case #%d: %lld\n", Case++, Min); } return 0; }