JZOJ 2933. 【NOIP2012模擬8.7】找位置
阿新 • • 發佈:2020-10-07
題目大意
有 \(n(1 \leq n \leq 10000)\) 個城鎮,由 \(1 \leq m \leq 50000\) 條無向道路連線。給出 \(k(1 \leq k \leq 5) 個超市\),現於剩下 \(n-k\) 個城鎮中選擇一個,使它到所有有超市的城鎮再回來總路程最短
分析
注意到 \(k\) 很小,那我們就可以列舉經過這些超市的順序,然後依次走最短路,再列舉一個另外出發城鎮,由最後一個超市返回
於是就完了
\(Code\)
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int N = 10005 , M = 50005; int n , m , k , tot , cnt; int a[N] , used[10] , b[10] , order[200][10] , vis[N] , dis[10][N] , h[N]; struct edge{ int to , nxt , w; }e[M << 1]; struct node{ int id , d; bool operator < (node c) const {return d > c.d;} }; priority_queue<node> q; void add(int u , int v , int w){e[++tot] = edge{v , h[u] , w} , h[u] = tot;} void dij(int s) { memset(vis , 0 , sizeof(vis)); for(register int i = 1; i <= n; i++) dis[s][i] = 1e8; dis[s][a[s]] = 0; while (!q.empty()) q.pop(); q.push((node){a[s] , 0}); while (!q.empty()) { node x = q.top(); q.pop(); if (vis[x.id]) continue; vis[x.id] = 1; for(register int i = h[x.id]; i; i = e[i].nxt) if (dis[s][x.id] + e[i].w < dis[s][e[i].to]) { dis[s][e[i].to] = dis[s][x.id] + e[i].w; q.push((node){e[i].to , dis[s][e[i].to]}); } } } void dfs(int x) { if (x > k) { ++cnt; for(register int i = 1; i <= k; i++) order[cnt][i] = b[i]; return; } for(register int i = 1; i <= k; i++) if (!used[i]) { used[i] = 1 , b[x] = i , dfs(x + 1); used[i] = 0 , b[x] = 0; } } void solve() { int ans = 2e9; dfs(1); for(register int i = 1; i <= k; i++) dij(i); memset(vis , 0 , sizeof vis); for(register int i = 1; i <= k; i++) vis[a[i]] = 1; for(register int i = 1; i <= cnt; i++) { int sum = 0; for(register int j = 2; j <= k; j++) sum = sum + dis[order[i][j - 1]][a[order[i][j]]]; if (sum > ans) continue; int Mi = 1e8; for(register int j = 1; j <= n; j++) if (!vis[j]) Mi = min(Mi , sum + dis[order[i][1]][j] + dis[order[i][k]][j]); ans = min(ans , Mi); } printf("%d" , ans); } int main() { scanf("%d%d%d" , &n , &m , &k); for(register int i = 1; i <= k; i++) scanf("%d" , &a[i]); int u , v , w; for(register int i = 1; i <= m; i++) scanf("%d%d%d" , &u , &v , &w) , add(u , v , w) , add(v , u , w); solve(); }