QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#186351#6402. MEXimum Spanning Treeucup-team228#TL 1ms10644kbC++177.2kb2023-09-23 18:00:382023-09-23 18:00:39

Judging History

你现在查看的是最新测评结果

  • [2023-09-23 18:00:39]
  • 评测
  • 测评结果:TL
  • 用时:1ms
  • 内存:10644kb
  • [2023-09-23 18:00:38]
  • 提交

answer

#include <iostream>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <queue>
#include <deque>
#include <cmath>
#include <algorithm>
#include <cassert>
#include <chrono>
#include <random>
#include <string>
#include <numeric>
#include <complex>
#include <tuple>
#include <utility>
#include <bitset>
#include <array>
#include <stack>
#include <sstream>
using namespace std;
typedef long long ll;
 
string to_string(string a) { return '"' + a + '"'; }
string to_string(char a) { return "'" + string(1, a) + "'"; }
string to_string(const char* a) { return to_string((string) a); }
string to_string(bool a) { return a ? "true" : "false"; }
template <class T1, class T2>
string to_string(pair<T1, T2> a) {
    return "(" + to_string(a.first) + ", " + to_string(a.second) + ")";
}
template <class T>
string to_string(T a) {
    bool first = true; string res = "{";
    for (const auto& i : a) {
        if (!first) res += ", ";
        first = false;
        res += to_string(i);
    }
    res += "}";
    return res;
}
void debug_out() { cerr << endl; }
template <class T1, class... T2>
void debug_out(T1 a, T2... b) {
    cerr << " " << to_string(a);
    debug_out(b...);
}
 
#ifdef LOCAL
#define out(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define out(...) 42
#endif

clock_t start_time; void start_timer() { start_time = clock(); }
double get_time() { return (double) (clock() - start_time) / CLOCKS_PER_SEC; }

void Solve();

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
    freopen("usr/share/man/man1/input.txt", "r", stdin);
#endif
    start_timer();
    Solve();
#ifdef LOCAL
    cerr << fixed << setprecision(3);
    cerr << endl << "Time spent: " << get_time() << endl;
#endif
    return 0;
}

// do something, stay focused
// look for stupid bugs
// guess, slow, stress
// don't overgeneralize
// don't rush

// don't waste time on standings

// SOLVE THE PROBLEM OR DIE TRYING
// THE SOLUTION IS ALWAYS SIMPLE
// THE CODE IS ALWAYS SHORT

const int N = 1005; // edges
const int K = 1005; // vertices / colors

struct Edge {
    int u, v;
};

struct Elem {
    int color;
    Edge edge;
    bool in_set = 0;
    int set_pos;
    int par;
};

vector<Elem> ground;
vector<int> indep;

struct GraphMatroid {
    struct Graph {
        vector<Edge> es;
        int par[K];
        int dep[K];
        int find(int v) {
            if (par[v] == v) return v;
            return par[v] = find(par[v]);
        }
        void unite(int u, int v) {
            u = find(u);
            v = find(v);
            if (u == v) return;
            if (dep[u] < dep[v]) swap(u, v);
            par[v] = u;
            if (dep[u] == dep[v]) dep[u]++;
        }
        void add_edge(Edge e) {
            es.push_back(e);
        }
        void reset() {
            es.clear();
        }
        int size() {
            return (int) es.size();
        }
        void build_dsu() {
            for (int i = 0; i < K; i++) {
                par[i] = i;
                dep[i] = 0;
            }
            for (Edge e : es) {
                unite(e.u, e.v);
            }
        }
        bool indep_with(Edge e) {
            return find(e.u) != find(e.v);
        }
    };
    Graph basis;
    Graph basis_without[K];
    bool oracle(int add) {
        return basis.indep_with(ground[add].edge);
    }
    bool oracle(int add, int rem) {
        int id = ground[rem].set_pos;
        return basis_without[id].indep_with(ground[add].edge);
    }
    void init() {
        basis.reset();
        for (int i = 0; i < indep.size(); i++) {
            basis_without[i].reset();
        }
        for (int i = 0; i < indep.size(); i++) {
            basis.add_edge(ground[indep[i]].edge);
            for (int j = 0; j < indep.size(); j++) {
                if (j != i) {
                    basis_without[j].add_edge(ground[indep[i]].edge);
                }
            }
        }
        basis.build_dsu();
        for (int i = 0; i < indep.size(); i++) {
            basis_without[i].build_dsu();
        }
    }
};

struct ColorfulMatroid {
    bool used[K];
    bool oracle(int add) {
        return !used[ground[add].color];
    }
    bool oracle(int add, int rem) {
        int add_col = ground[add].color;
        int rem_col = ground[rem].color;
        if (!used[add_col]) return 1;
        return add_col == rem_col;
    }
    void init() {
        for (int i = 0; i < K; i++) {
            used[i] = 0;
        }
        for (int i : indep) {
            used[ground[i].color] = 1;
        }
    }
};

GraphMatroid graph;
ColorfulMatroid color;

void init() {
    ground.clear();
    indep.clear();
}

bool augment() {
    static const int kSource = -1;
    static const int kNotVisited = -2;
    static const int kNotFound = -3;
    graph.init();
    color.init();
    for (int i = 0; i < ground.size(); i++) {
        ground[i].par = kNotVisited;
    }
    int id = kNotFound;
    queue<int> q;
    for (int i = 0; i < ground.size(); i++) {
        if (color.oracle(i)) {
            ground[i].par = kSource;
            q.push(i);
        }
    }
    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        if (ground[cur].in_set) {
            for (int to = 0; to < ground.size(); to++) {
                if (ground[to].par != kNotVisited) continue;
                if (!color.oracle(to, cur)) continue;
                ground[to].par = cur;
                q.push(to);
            }
            continue;
        }
        if (graph.oracle(cur)) {
            id = cur;
            break;
        }
        for (int to : indep) {
            if (ground[to].par != kNotVisited) continue;
            if (!graph.oracle(cur, to)) continue;
            ground[to].par = cur;
            q.push(to);
        }
    }
    if (id == kNotFound) {
        return 0;
    }
    do {
        ground[id].in_set ^= 1;
        id = ground[id].par;
    } while (id != kSource);
    indep.clear();
    for (int i = 0; i < ground.size(); i++) {
        if (!ground[i].in_set) continue;
        ground[i].set_pos = (int) indep.size();
        indep.push_back(i);
    }
    return 1;
}

void add_element(Edge edge, int color) {
    ground.emplace_back();
    ground.back().edge = edge;
    ground.back().color = color;
}

void matroid_intersection() {
    while (augment());
}

vector<Edge> es[N];

void Solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        es[w].push_back({u, v});
    }
    if (es[0].empty()) {
        cout << "0\n";
        return;
    }
    int l = 0;
    int r = n;
    while (l < r) {
        init();
        int mid = (l + r) / 2 + 1;
        for (int w = 0; w <= mid; w++) {
            for (Edge e : es[w]) {
                add_element(e, w);
            }
        }
        matroid_intersection();
        if (indep.size() == mid + 1) l = mid;
        else r = mid - 1;
    }
    cout << l + 1 << "\n";
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 10644kb

input:

4 4
1 2 0
2 3 1
1 3 1
3 4 2

output:

3

result:

ok 1 number(s): "3"

Test #2:

score: -100
Time Limit Exceeded

input:

1000 1000
647 790 6
91 461 435
90 72 74
403 81 240
893 925 395
817 345 136
88 71 821
831 962 53
164 270 298
14 550 317
99 580 81
26 477 488
977 474 861
413 483 167
872 675 17
819 327 449
594 242 68
381 983 319
867 582 358
869 225 669
274 352 392
40 388 998
246 477 44
508 979 286
483 776 71
580 438 6...

output:


result: