제출 #1272886

#제출 시각아이디문제언어결과실행 시간메모리
1272886julia_08Cities (BOI16_cities)C++20
100 / 100
1524 ms34760 KiB
#include <bits/stdc++.h>
using namespace std;
 
using ll = long long;
 
const int MAXN = 2e5 + 10;
const ll INF = 1e18;
 
ll dist[MAXN][5], marc[MAXN][5];
 
ll dist_ans[MAXN][2], marc_ans[MAXN][2];
 
vector<pair<int, ll>> adj[MAXN];
 
vector<int> cities;
 
int n, k;
 
void dijkstra(int k){
 
  for(int i=1; i<=n; i++) dist[i][k] = INF;
 
  priority_queue<pair<ll, int>> q;
 
  q.push({0, cities[k]});
  dist[cities[k]][k] = 0;
 
  while(!q.empty()){
 
    int v = q.top().second;
    q.pop();
 
    if(marc[v][k]) continue;
    marc[v][k] = 1;
 
    for(auto [u, w] : adj[v]){
      if(dist[v][k] + w < dist[u][k]){
        dist[u][k] = dist[v][k] + w;
        q.push({-dist[u][k], u});
      }
    }
 
  }
 
}
 
void dijkstra_ans(int v, int x){
 
  for(int i=1; i<=(n + 2); i++){
    marc_ans[i][x] = 0;
    dist_ans[i][x] = INF;
  }
 
  priority_queue<pair<ll, int>> q;
 
  q.push({0, v});
  dist_ans[v][x] = 0;
 
  while(!q.empty()){
 
    int v = q.top().second;
    q.pop();
 
    if(marc_ans[v][x]) continue;
    marc_ans[v][x] = 1;
 
    for(auto [u, w] : adj[v]){
      if(dist_ans[v][x] + w < dist_ans[u][x]){
        dist_ans[u][x] = dist_ans[v][x] + w;
        q.push({-dist_ans[u][x], u});
      }
    }
 
  }
 
}
 
void solve_two(){
 
  cout << dist[cities[1]][0] << "\n";
 
}
 
void solve_three(){
 
  ll ans = INF;
 
  for(int i=1; i<=n; i++) ans = min(ans, dist[i][0] + dist[i][1] + dist[i][2]);
 
  cout << ans << "\n";
 
}
 
void solve_four(){
 
  ll ans = INF;
 
  int A = n + 1, B = n + 2;
 
  for(int a=0; a<k; a++){
    for(int b=(a + 1); b<k; b++){
 
      int c = -1, d = -1;
 
      for(int t=0; t<k; t++){
 
        if(t == a || t == b) continue;
 
        if(c == -1){
          c = t;
        } else d = t;
 
      }
 
      // A -> (a, b), (c, d) -> B
 
      adj[A].clear();
 
      for(int i=1; i<=n; i++){
        adj[A].push_back({i, dist[i][a] + dist[i][b]});
        adj[i].push_back({B, dist[i][c] + dist[i][d]});
      }
 
      dijkstra_ans(A, 0);
      ans = min(ans, dist_ans[B][0]);
 
      // tira o ultimo, que foi o B
      for(int i=1; i<=n; i++) adj[i].pop_back();
 
    }
  }
 
  cout << ans << "\n";
 
} 
 
void solve_five(){
  
  ll ans = INF;
  
  int A = n + 1, B = n + 2;
  
  for(int i=1; i<=n; i++){
    adj[A].push_back({i, 0});
    adj[B].push_back({i, 1});
  }
  
  for(int a=0; a<k; a++){
    
    vector<int> possible;
    
    for(int c=0; c<k; c++) if(c != a) possible.push_back(c);
    
    int b = possible[0];
    
    for(int l=1; l<4; l++){
      
      int c = possible[l];
      
      int d = possible[2], e = possible[3];
      
      if(l == 2) d = possible[1];
      if(l == 3) e = possible[1];
      
      for(int i=1; i<=n; i++){
        adj[A][i - 1].second = dist[i][b] + dist[i][c];
        adj[B][i - 1].second = dist[i][d] + dist[i][e];
      }
    
      dijkstra_ans(A, 0);
      dijkstra_ans(B, 1);
            
      for(int i=1; i<=n; i++) ans = min(ans, dist_ans[i][0] + dist_ans[i][1] + dist[i][a]);
      
    }
    
  }

  cout << ans << "\n";
  
}
 
int main(){
  cin.tie(0)->sync_with_stdio(0);
 
  int m; cin >> n >> k >> m;
 
  cities.resize(k);
 
  for(int i=0; i<k; i++) cin >> cities[i];
 
  while(m--){
    int a, b, c; cin >> a >> b >> c;
    adj[a].push_back({b, c});
    adj[b].push_back({a, c});
  }
 
  for(int i=0; i<k; i++) dijkstra(i);
 
  if(k == 2){
    solve_two();
    return 0;
  }
 
  if(k == 3){
    solve_three();
    return 0;
  }
  
  if(k == 4){
    solve_four();
    return 0;
  }
 
  solve_five();
 
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...