QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#696530#6402. MEXimum Spanning TreeNTTWA 1ms3640kbC++236.8kb2024-10-31 23:10:572024-10-31 23:10:57

Judging History

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

  • [2024-10-31 23:10:57]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3640kb
  • [2024-10-31 23:10:57]
  • 提交

answer

#pragma GCC optimize("Ofast,inline")
//verification of Huang, Chien-Chung; Kakimura, Naonori; Kamiyama, Naoyuki (2019-09-01). "Exact and approximation algorithms for weighted matroid intersection". Mathematical Programming. 177 (1): 85–112. doi:10.1007/s10107-018-1260-x. hdl:2324/1474903. ISSN 1436-4646. S2CID 254138118.
//based on https://qoj.ac/submission/548815
#include <bits/stdc++.h>
// #include"C:/code/deb_20.cpp"
using ll = long long;
using i128=__int128;
using ld = long double;
#define int ll
template<typename T>using V=std::vector<T>;
using vi=V<int>;
using vvi=V<vi>;
using namespace std;
constexpr ll M=ll(1e18)+9;

#define len(a) int((a).size())
#define all(a) begin(a), end(a)
#define rep(i, n) for (int i = 0; i < (n); i++)

template<typename T, typename A, typename B>
vector<T> matroid_intersection(const vector<T>& ground_set, const A& matroid1, const B& matroid2) {
    int n = ground_set.size();
    vector<char> in_set(n), in_matroid1(n), in_matroid2(n);
    vector<bool> used(n);
    vector<int> par(n), left, right;
    left.reserve(n);
    right.reserve(n);

    while (true) {
        A m1 = matroid1;
        B m2 = matroid2;
        left.clear();
        right.clear();
        for (int i = 0; i < n; i++) {
            if (in_set[i]) {
                m1.add(ground_set[i]);
                m2.add(ground_set[i]);
                left.push_back(i);
            } else {
                right.push_back(i);
            }
        }

        fill(all(in_matroid1), 0);
        fill(all(in_matroid2), 0);
        bool found = false;
        for (int i : right) {
            in_matroid1[i] = m1.independed_with(ground_set[i]);
            in_matroid2[i] = m2.independed_with(ground_set[i]);
            if (in_matroid1[i] && in_matroid2[i]) {
                in_set[i] = 1;
                found = true;
                break;
            }
        }

        if (found) {
            continue;
        }

        fill(all(used), false);
        fill(all(par), -1);
        queue<int> que;
        for (int i : right) {
            if (in_matroid1[i]) {
                used[i] = true;
                que.push(i);
            }
        }

        while (!que.empty() && !found) {
            int v = que.front();
            que.pop();

            if (in_set[v]) {
                A m = matroid1;
                for (auto i : left) {
                    if (i != v) {
                        m.add(ground_set[i]);
                    }
                }

                for (auto u : right) {
                    if (!used[u] && m.independed_with(ground_set[u])) {
                        par[u] = v;
                        used[u] = true;
                        que.push(u);

                        if (in_matroid2[u]) {
                            found = true;
                            for (; u != -1; u = par[u]) {
                                in_set[u] ^= 1;
                            }
                            break;
                        }
                    }
                }
            } else {
                B m = m2;
                m.add_extra(ground_set[v]);
                for (auto u : left) {
                    if (!used[u] && m.independed_without(ground_set[u])) {
                        par[u] = v;
                        used[u] = true;
                        que.push(u);
                    }
                }
            }
        }

        if (!found) {
            break;
        }
    }

    vector<T> res;
    for (int i = 0; i < n; i++) {
        if (in_set[i]) {
            res.push_back(ground_set[i]);
        }
    }
    return res;
}

struct item {
    int v, u, w;
};

struct colorful_matroid {
    vector<int> cnt;
    int cnt_bad = 0;

    colorful_matroid(int n) : cnt(n + 1) {}

    void add(const item& item) {
        auto x = item.w;
        assert(cnt[x] == 0);
        cnt[x]++;
    }

    bool independed_with(const item& item) const {
        auto x = item.w;
        return cnt[x] == 0;
    }

    void add_extra(const item& item) {
        auto x = item.w;
        cnt_bad += cnt[x] == 1;
        cnt[x]++;
    }

    bool independed_without(const item& item) const {
        auto x = item.w;
        return cnt_bad == 0 || cnt[x] == 2;
    }
};

struct graph_matroid {
    vector<int> par;

    graph_matroid(int n) : par(n) {
        iota(all(par), 0);
    }

    int root(int v) {
        return par[v] == v ? v : par[v] = root(par[v]);
    }

    bool independed_with(const item& item) {
        int v = item.v, u = item.u;
        return root(v) != root(u);
    }

    void add(const item& item) {
        int v = item.v, u = item.u;
        assert(root(v) != root(u));
        par[root(v)] = root(u);
    }
};

vi&operator+=(vi&a,const vi&b){for(int i=0;i<ssize(a);++i)(a[i]+=b[i])%=M;return a;}
vi&operator*=(vi&a,const ll&b){for(auto&&x:a)x=x*i128(b)%M;return a;}
#define GEN_OP(op) auto operator op(auto a,const auto&b){return a op##= b;}
GEN_OP(+)
GEN_OP(*)
// struct Matrix:vvi{
// 	
// };
ll qpow(i128 a,auto b){ll res=1;for(;b;a=a*a%M,b>>=1)if(b&1)res=res*a%M;return res;}
using Matrix=vvi;
int rnk(Matrix a){
	int n=ssize(a),m=ssize(a[0]),i=0,j=0;
	for(;i<n&&j<m;++j){
		int r=i;
		for(;r<n;++r)if(a[r][j])break;
		if(r<n&&a[r][j]){
			if(r!=i)std::swap(a[r],a[i]);
			for(int l=i+1;l<n;++l){
				i128 fct=i128(M-a[l][j])*qpow(a[i][j],M-2)%M;
				if(fct)a[l]+=a[i]*fct;
			}
			++i;
		}
	}
	return i;
}
mt19937_64 rng(19260817);
auto rnd(auto a,auto b){return std::uniform_int_distribution(a,b)(rng);}
signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    int n, m;
    cin >> n >> m;
    vector<item> st(m);
    for (int i = 0; i < m; i++) {
        cin >> st[i].v >> st[i].u >> st[i].w;
        st[i].v--, st[i].u--;
    }

    auto possible = [&](int mex) {
    	// if constexpr(false){
	        vector<item> cur_st;
	        for (auto item : st) {
	            if (item.w < mex) {
	                cur_st.push_back(item);
	            }
	        }
	        colorful_matroid cm(n);
	        graph_matroid g(n);
	        auto resoid=len(matroid_intersection(cur_st, g, cm));
    	// }else{
    		vvi ma(n+m,vi(mex+m));
    		int resix=0;
    		for(int i=0;i<m;++i)if(st[i].w<mex){
    			resix--;
    			ma[n+i][mex+i]=rnd(1ll,M-1);
    			auto x=rnd(1ll,M-1);
    			ma[st[i].v][mex+i]=+x;
    			ma[st[i].u][mex+i]=M-x;
    			ma[n+i][st[i].w]=1;
    		}
			resix+=rnk(ma);
    	// }
    	// debug(mex,resoid,resix);
    	assert(resix==resoid);
    	return resix;
    };

    int lb = 0, rb = n + 1;
    while (rb - lb > 1) {
        int mid = (lb + rb) / 2;
        (possible(mid) ? lb : rb) = mid;
    }
    cout << lb << '\n';
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 1ms
memory: 3640kb

input:

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

output:

4

result:

wrong answer 1st numbers differ - expected: '3', found: '4'