QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#696593 | #6402. MEXimum Spanning Tree | NTT | RE | 45ms | 3796kb | C++23 | 7.1kb | 2024-10-31 23:42:34 | 2024-10-31 23:42:36 |
Judging History
answer
#pragma GCC optimize("Ofast")
//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;
vi rdw(m);
vector<item> st(m);
for (int i = 0; i < m; i++) {
rdw[i]=rnd(1ll,M-1);
cin >> st[i].v >> st[i].u >> st[i].w;
st[i].v--, st[i].u--;
assert(st[i].v!=st[i].u);
}
std::ranges::sort(st,{},&item::w);
int jcnt=0;
auto possible = [&](int mex) {
int m=0;
// if constexpr(false){
vector<item> cur_st;
for (auto item : st) {
if (item.w < mex) {
++m;
cur_st.push_back(item);
}
}
colorful_matroid cm(n);
graph_matroid g(n);
auto resoid=len(matroid_intersection(cur_st, g, cm));
if(++jcnt>=0)return resoid==mex;
// }else{
vvi ma(n+m,vi(m));
vi vis(mex,-1);
int resix=0;
for(int i=0;i<m;++i)if(st[i].w<mex){
resix--;
if(!~vis[st[i].w]){
vis[st[i].w]=i;
resix++;
}else{
ma[n+i][vis[st[i].w]]=-rdw[vis[st[i].w]];
ma[n+i][i]=rdw[i];
}
auto x=rnd(1ll,M-1);
ma[st[i].v][i]=+x;
ma[st[i].u][i]=M-x;
}
resix+=rnk(ma);
// }
// debug(mex,resoid,resix);
// cerr<<mex<<' '<<resoid<<' '<<resix<<'\n';
assert(resix==resoid);
return resix==mex;
};
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: 100
Accepted
time: 1ms
memory: 3568kb
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: 0
Accepted
time: 19ms
memory: 3780kb
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:
502
result:
ok 1 number(s): "502"
Test #3:
score: 0
Accepted
time: 45ms
memory: 3796kb
input:
900 1000 232 890 107 425 399 19 5 74 753 105 333 163 779 42 582 359 647 524 767 409 48 239 780 443 484 489 546 97 634 562 627 866 714 500 357 590 60 728 591 407 686 210 547 32 370 76 772 500 407 584 772 73 699 69 332 847 516 829 754 727 562 756 678 819 303 128 781 667 263 535 672 767 89 762 216 878 ...
output:
801
result:
ok 1 number(s): "801"
Test #4:
score: -100
Runtime Error
input:
500 1000 381 118 230 258 331 21 403 71 207 170 2 125 467 99 6 369 100 492 70 187 352 99 163 123 135 51 352 461 175 486 275 194 236 299 14 19 16 1 68 7 229 316 235 433 320 411 179 463 112 329 326 464 169 52 377 93 51 84 336 335 42 240 379 182 496 344 377 481 195 88 286 491 199 425 165 37 292 44 197 2...