제출 #1328282

#제출 시각아이디문제언어결과실행 시간메모리
1328282_callmelucian시간이 돈 (balkan11_timeismoney)C++17
100 / 100
329 ms592 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using pl = pair<ll,ll>;
using pii = pair<int,int>;
using tpl = tuple<int,int,int>;

#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())

struct Point {
    int x, y;

    Point() : x(0), y(0) {}
    Point (int a, int b) : x(a), y(b) {}

    Point operator+ (const Point &o) const { return Point(x + o.x, y + o.y); }
    Point operator- (const Point &o) const { return Point(x - o.x, y - o.y); }

    friend int dot (const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
    friend int cross (const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }

    friend istream& operator>> (istream &inp, Point &p) { return inp >> p.x >> p.y, inp; }
    friend ostream& operator<< (ostream &oup, const Point &p) {
        return oup << "(" << p.x << ", " << p.y << ")", oup;
    }
};

struct Line {
    int A, B, C;

    Line() : A(0), B(0), C(0) {}
    Line (Point a, Point b) : A(b.y - a.y), B(a.x - b.x), C(cross(a, b)) {}

    bool onLine (const Point &p) { return A * p.x + B * p.y == C; }
};

struct DSU {
    vector<int> lab;
    DSU (int sz) : lab(sz + 1, -1) {}

    int get (int u) {
        if (lab[u] < 0) return u;
        return lab[u] = get(lab[u]);
    }

    bool unite (int a, int b) {
        a = get(a), b = get(b);
        if (a == b) return false;
        if (-lab[a] < -lab[b]) swap(a, b);
        lab[a] += lab[b], lab[b] = a;
        return true;
    }
};

const int mn = 1e4 + 4;

struct Edge {
    int a, b, timeCost, moneyCost;

    Edge() : a(0), b(0), timeCost(0), moneyCost(0) {}
    Edge (int a, int b, int t, int m) : a(a), b(b), timeCost(t), moneyCost(m) {}

    friend istream& operator>> (istream &inp, Edge &e) {
        return inp >> e.a >> e.b >> e.timeCost >> e.moneyCost, inp;
    }
} edges[mn];

int n, m, ans = INT_MAX;
int optAlpha, optBeta;

Point returnMst (int alpha, int beta) {
    auto cost = [&] (const Edge &a) { return alpha * a.timeCost + beta * a.moneyCost; };
    auto cmp = [&] (const Edge &a, const Edge &b) { return cost(a) < cost(b); };
    sort(edges, edges + m, cmp);

    int sumTime = 0, sumMoney = 0;
    DSU dsu(n);
    for (int i = 0; i < m; i++)
        if (dsu.unite(edges[i].a, edges[i].b))
            sumTime += edges[i].timeCost, sumMoney += edges[i].moneyCost;
    if (sumTime * sumMoney < ::ans)
        ::ans = sumTime * sumMoney, optAlpha = alpha, optBeta = beta;
    return Point(sumTime, sumMoney);
}

void solve (const Point &a, const Point &b) {
    Line curLine(a, b);
    Point tryPoint = returnMst(curLine.A, curLine.B);
    // cout << "solve " << a << " " << b << " found " << tryPoint << "\n";
    if (!curLine.onLine(tryPoint))
        solve(a, tryPoint), solve(tryPoint, b);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    // read input
    cin >> n >> m;
    for (int i = 0; i < m; i++) cin >> edges[i];

    // find optimal solution
    solve(returnMst(0, 1), returnMst(1, 0));
    
    // reconstruct solution
    int sumTime = 0, sumMoney = 0;
    auto cost = [&] (const Edge &a) { return optAlpha * a.timeCost + optBeta * a.moneyCost; };
    auto cmp = [&] (const Edge &a, const Edge &b) { return cost(a) < cost(b); };
    sort(edges, edges + m, cmp);

    DSU dsu(n);
    vector<pii> edgeList;
    for (int i = 0; i < m; i++) {
        if (!dsu.unite(edges[i].a, edges[i].b)) continue;
        edgeList.emplace_back(edges[i].a, edges[i].b);
        sumTime += edges[i].timeCost;
        sumMoney += edges[i].moneyCost;
    }

    cout << sumTime << " " << sumMoney << "\n";
    for (auto [a, b] : edgeList)
        cout << a << " " << b << "\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...