Cod sursa(job #1709655)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 28 mai 2016 13:15:33
Problema Politie Scor 100
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 2.7 kb
#include <bits/stdc++.h>

using namespace std;

const int N_MAX = 250005;
const int D_MAX = 250005;
const int FACTOR = 1000000;

class Edge {
   public:
      int from;
      int to;
      int risk;
      
      Edge(int _from = 0, int _to = 0, int _risk = 0) :
         from(_from), to(_to), risk(_risk) {}
};

int N, M, D, P;
mt19937 rGen(chrono :: high_resolution_clock :: now().time_since_epoch().count());
vector<Edge> edges[D_MAX];
int father[N_MAX];
unordered_map<int64_t, int> minRisk;
set<int, greater<int>> usedRisks;
vector<pair<int, pair<int, int>>> temp;

inline int64_t PairToLong(int x, int y) {
   return 1LL * x * FACTOR + y;
}

inline pair<int, int> LongToPair(int64_t x) {
   return make_pair(x / FACTOR, x % FACTOR);
}

int Find(int x) {
   if(x != father[x])
      father[x] = Find(father[x]);
   return father[x];
}

void Merge(int x, int y) {
   int fx = Find(x);
   int fy = Find(y);
   
   if(fx != fy) {
      if(rGen() & 1) swap(fx, fy);
      father[fx] = fy;
   }
}

int main() {
   ifstream f("politie.in");
   ofstream g("politie.out");
   
   f >> N >> M >> D >> P;
   
   for(int i = 1, x, y, d, r; i <= M; i++) {
      f >> x >> y >> d >> r;
      edges[d].push_back(Edge(x, y, r));
   }
   
   for(int i = 1; i <= N; i++)
      father[i] = i;
   
   for(int i = 1; i <= D; i++) {
      minRisk.clear();
      for(vector<Edge> :: iterator it = edges[i].begin(); it != edges[i].end(); ++it) {
         int x = min(Find(it->from), Find(it->to));
         int y = max(Find(it->from), Find(it->to));
         if(x != y) {
            int64_t key = PairToLong(x, y);
            unordered_map<int64_t, int> :: iterator mapIt = minRisk.find(key);
            if(mapIt == minRisk.end()) {
               minRisk.insert(make_pair(key, it->risk));
            } else {
               mapIt->second = min(mapIt->second, it->risk);
            }
         }
      }
      temp.clear();
      for(unordered_map<int64_t, int> :: iterator it = minRisk.begin(); it != minRisk.end(); ++it) {
         pair<int, int> key = LongToPair(it->first);
         int x = key.first;
         int y = key.second;
         temp.push_back(make_pair(it->second, make_pair(x, y)));
      }
      sort(temp.begin(), temp.end());
      for(vector<pair<int, pair<int, int>>> :: iterator it = temp.begin(); it != temp.end(); it++) {
         if(Find(it->second.first) != Find(it->second.second)) {
            Merge(it->second.first, it->second.second);
            usedRisks.insert(it->first);
         }
      } 
   }
   
   set<int, greater<int>> :: iterator it = usedRisks.begin();
   for(int i = 1; i <= P; i++, it++)
      g << *it << '\n';
   
   return 0;
}