Cod sursa(job #1709575)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 28 mai 2016 12:55:43
Problema Politie Scor 0
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 2.45 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];
map<int64_t, int> minRisk;
vector<int> usedRisks;

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);
            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);
            }
         }
      }
      for(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;
         if(Find(x) != Find(y)) {
            Merge(x, y);
            usedRisks.push_back(it->second);
         }
      }
   }
   
   sort(usedRisks.begin(), usedRisks.end(), greater<int>());
   
   for(int i = 0, j = 0; i < usedRisks.size() && j < P; i++) {
      if(i == 0 || usedRisks[i] != usedRisks[i - 1]) {
         ++j;
         g << usedRisks[i] << '\n';
      }
   }
   
   return 0;
}