Advertisement
erek1e

EGOI '23 - Bikes vs Cars (69pts)

Jul 21st, 2023
912
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.49 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. const int INF = 1e7;
  6.  
  7. // DSU
  8. int root(int i, vector<int> &parent) {
  9.     return parent[i] < 0 ? i : (parent[i] = root(parent[i], parent));
  10. }
  11. void unite(int i, int j, vector<int> &parent) {
  12.     i = root(i, parent), j = root(j, parent);
  13.     if (i == j) return;
  14.     if (parent[i] > parent[j]) swap(i, j);
  15.     parent[i] += parent[j];
  16.     parent[j] = i;
  17. }
  18.  
  19. vector<tuple<int, int, int>> solve() {
  20.     int n, W; cin >> n >> W;
  21.     vector<vector<int>> B(n, vector<int>(n)), C(n, vector<int>(n));
  22.     for (int i = 1; i < n; ++i) {
  23.         for (int j = 0; j < i; ++j) cin >> C[i][j], C[j][i] = C[i][j];
  24.     }
  25.     int mnB = INF, mxB = 0;
  26.     for (int i = 1; i < n; ++i) {
  27.         for (int j = 0; j < i; ++j) {
  28.             cin >> B[i][j], B[j][i] = B[i][j];
  29.             mnB = min(mnB, B[i][j]);
  30.             mxB = max(mxB, B[i][j]);
  31.         }
  32.     }
  33.    
  34.     vector<tuple<int, int, int>> streets;
  35.     if (mnB == mxB) {
  36.         for (int i = 0; i < n-1; ++i) streets.emplace_back(i, i+1, mnB);
  37.         int smallC = W-mnB; // cannot build C lower than this
  38.        
  39.         // sort C by weight
  40.         vector<tuple<int, int, int>> edges;
  41.         for (int i = 0; i < n; ++i) {
  42.             for (int j = i+1; j < n; ++j) {
  43.                 if (C[i][j] < smallC) return {};
  44.                 edges.emplace_back(C[i][j], i, j);
  45.             }
  46.         }
  47.         sort(edges.begin(), edges.end());
  48.  
  49.         vector<int> parent(n, -1);
  50.         while (!edges.empty()) {
  51.             int curC = get<0>(edges.back());
  52.             for (int i = (int)edges.size()-1; i >= 0 && get<0>(edges[i]) == curC; --i) {
  53.                 int a = get<1>(edges[i]), b = get<2>(edges[i]);
  54.                 if (root(a, parent) == root(b, parent)) return {}; // reachable with larger edges
  55.             }
  56.             for (int i = (int)edges.size()-1; i >= 0 && get<0>(edges[i]) == curC; --i) {
  57.                 int a = get<1>(edges[i]), b = get<2>(edges[i]);
  58.                 if (root(a, parent) != root(b, parent)) unite(a, b, parent), streets.emplace_back(a, b, W-curC);
  59.                 edges.pop_back();
  60.             }
  61.         }
  62.         return streets;
  63.     } else if (W == 1) {
  64.         vector<int> parentB(n, -1), parentC(n, -1), parent(n, -1);
  65.         for (int i = 0; i < n; ++i) {
  66.             for (int j = i+1; j < n; ++j) {
  67.                 if (B[i][j] == 1) unite(i, j, parentB), unite(i, j, parent);
  68.                 if (C[i][j] == 1) unite(i, j, parentC), unite(i, j, parent);
  69.             }
  70.         }
  71.         if (parent[root(0, parent)] != -n) return {}; // all connected
  72.         for (int i = 0; i < n; ++i) {
  73.             for (int j = i+1; j < n; ++j) {
  74.                 if (B[i][j] == 0 && root(i, parentB) == root(j, parentB)) return {};
  75.                 if (C[i][j] == 0 && root(i, parentC) == root(j, parentC)) return {};
  76.             }
  77.         }
  78.  
  79.         for (int i = 0; i < n; ++i) {
  80.             if (parentB[i] >= 0) streets.emplace_back(i, root(i, parentB), 1);
  81.             if (parentC[i] >= 0) streets.emplace_back(i, root(i, parentC), 0);
  82.         }
  83.  
  84.         return streets;
  85.     } else {
  86.         vector<vector<int>> dB(n, vector<int>(n, -1)), dC(n, vector<int>(n, -1));
  87.         for (int i = 0; i < n; ++i) {
  88.             for (int j = i+1; j < n; ++j) {
  89.                 if (B[i][j] + C[i][j] >= W) {
  90.                     streets.emplace_back(i, j, B[i][j]);
  91.                     dB[j][i] = dB[i][j] = max(dB[i][j], B[i][j]);
  92.                     streets.emplace_back(i, j, W-C[i][j]);
  93.                     dC[j][i] = dC[i][j] = max(dC[i][j], C[i][j]);
  94.                 }
  95.             }
  96.         }
  97.  
  98.         // Floyd
  99.         for (int k = 0; k < n; ++k) {
  100.             for (int i = 0; i < n; ++i) {
  101.                 for (int j = 0; j < n; ++j) {
  102.                     dB[i][j] = max(dB[i][j], min(dB[i][k], dB[k][j]));
  103.                     dC[i][j] = max(dC[i][j], min(dC[i][k], dC[k][j]));
  104.                 }
  105.             }
  106.         }
  107.  
  108.         for (int i = 0; i < n; ++i) {
  109.             for (int j = i+1; j < n; ++j) {
  110.                 if (dB[i][j] != B[i][j] || dC[i][j] != C[i][j]) return {};
  111.             }
  112.         }
  113.         return streets;
  114.     }
  115. }
  116.  
  117. int main() {
  118.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  119.     vector<tuple<int, int, int>> streets = solve();
  120.     if (streets.empty()) {
  121.         cout << "NO" << endl;
  122.     } else {
  123.         cout << streets.size() << '\n';
  124.         for (auto [u, v, b] : streets) cout << u << ' ' << v << ' ' << b << '\n';
  125.     }
  126.     return 0;
  127. }
  128.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement