Submission #1342142

#TimeUsernameProblemLanguageResultExecution timeMemory
1342142Math4Life2020Keys (IOI21_keys)C++20
20 / 100
3097 ms41988 KiB
#include "keys.h"
#include <bits/stdc++.h>
using namespace std;

using ll = int; using pii = pair<ll,ll>; 

const ll Nm = 3e5+5;
vector<pair<pii,ll>> edg; //{u,v},c

ll dsuf[Nm];
map<ll,vector<ll>> mop[Nm]; //map: key -> edge vector to open 
set<ll> akey[Nm]; //active keys
vector<ll> iedg[Nm];
vector<bool> iact(Nm,0); //initially activated?
vector<ll> nelem(Nm,1); //number of elements in this group

ll getf(ll a) {
    if (dsuf[a]==a) {
        return a;
    }
    dsuf[a]=getf(dsuf[a]);
    return dsuf[a];
}

void mrg(ll a, ll b) {
    ll _a = a; ll _b = b;
    a = getf(a); b = getf(b);
    if (a==b) {
        return;
    }
    //cout << "implementing merge: "<<_a<<" with "<<_b<<"\n";
    if (nelem[a]>nelem[b]) {
        swap(a,b);
    }
    dsuf[a]=b;
    nelem[b]+=nelem[a];
    //merge numbers
    vector<ll> emrg;
    for (ll x: akey[a]) {
        if (mop[b].find(x)!=mop[b].end()) {
            for (ll m: mop[b][x]) {
                emrg.push_back(m);
            }
        }
        akey[b].insert(x);
    }
    for (auto A0: mop[a]) {
        ll k0 = A0.first; vector<ll> vedg = A0.second;
        if (akey[b].find(k0)!=akey[b].end()) {
            for (ll m: vedg) {
                emrg.push_back(m);
            }
        }
        for (ll m: vedg) {
            mop[b][k0].push_back(m);
        }
    }
    if (!iact[_a]) {
        iact[_a]=1;
        for (ll m: iedg[_a]) {
            emrg.push_back(m);   
        }
    }
    if (!iact[_b]) {
        iact[_b]=1;
        for (ll m: iedg[_b]) {
            emrg.push_back(m);   
        }
    }
    for (ll m: emrg) {
        ll x = edg[m].first.first; 
        ll y = edg[m].first.second;
        mrg(x,y);
    }
}

vector<int> find_reachable_fast(vector<int> r, vector<int> u, vector<int> v, vector<int> c) {
    ll N = r.size(); ll M = u.size();
    for (ll i=0;i<N;i++) {
        dsuf[i]=i;
        mop[i].clear();
        akey[i].clear();
        iedg[i].clear();
        iact[i]=0;
        nelem[i]=1;
    }
    for (ll i=0;i<N;i++) {
        akey[i].insert(r[i]);
    }
    vector<pair<pii,ll>> adj[N]; //{vertex, key type},edge index
    edg.clear();
    for (ll m=0;m<M;m++) {
        edg.push_back({{u[m],v[m]},c[m]});
        adj[u[m]].push_back({{v[m],c[m]},m});
        adj[v[m]].push_back({{u[m],c[m]},m});
        mop[u[m]][c[m]].push_back(m);
        mop[v[m]][c[m]].push_back(m);
    }
    vector<pii> fadj(N,{-1,-1}); //{vertex, key type}
    vector<ll> vblk; 
    for (ll i=0;i<N;i++) {
        for (auto A0: adj[i]) {
            pii p0 = A0.first;
            if (r[i]==p0.second) {
                fadj[i]=p0;
                iedg[i].push_back(A0.second);
            }
        }
        if (fadj[i].first==-1) {
            vblk.push_back(i);
        }
    }
    if (vblk.size()!=0) {
        //cout << "early terminate\n";
        vector<ll> vans(N,0);
        for (ll x: vblk) {
            vans[x]=1;
        }
        return vans;
    }
    vector<bool> found(N,0); //get all cycles
    vector<bool> ocyc(N,0); //on cycle?
    vector<ll> ec; //edges that follow from cycle terms
    for (ll i=0;i<N;i++) {
        ll x = i;
        ll y = i;
        for (ll t=0;t<=N;t++) {
            x = fadj[x].first;
            if (x==y) {
                ocyc[i]=1;
            }
        }
    }
    // for (ll i=0;i<N;i++) {
    //     if (found[i]) {
    //         continue;
    //     }
    //     //cout << "cycle find at i="<<i<<"\n";
    //     ll x = i;
    //     ll y = i;
    //     bool bbrk = 0;
    //     vector<ll> vnum; vnum.push_back(i);
    //     do {
    //         if (found[x]) {
    //             bbrk = 1; break;
    //         }
    //         x = fadj[x].first;
    //         vnum.push_back(x);
    //         y = fadj[fadj[y].first].first;
    //     } while (x!=y);
    //     if (bbrk) {
    //         for (ll z: vnum) {
    //             found[z]=1;
    //         }
    //         continue;
    //     }
    //     do {
    //         //mrg(x,fadj[x].first);
    //         x = fadj[x].first;
    //         ocyc[x]=1;
    //         //cout << "find x="<<x<<"\n";
    //     } while (x!=y);
    //     for (ll z: vnum) {
    //         found[z]=1;
    //     }
    // }
    for (ll x=0;x<N;x++) {
        if (ocyc[x]==1) {
            //cout << "x="<<x<<" on initial cycle\n";
            if (mop[x].find(r[x])!=mop[x].end()) {
                for (ll m: mop[x][r[x]]) {
                    ec.push_back(m);
                }
            }
        }
    }
    for (ll m: ec) {
        ll x = edg[m].first.first; 
        ll y = edg[m].first.second;
        mrg(x,y);
    }
    ll minp = N+1;
    vector<ll> vconstr;
    for (ll i=0;i<N;i++) {
        ll x = getf(i);
        //cout << "i="<<i<<", x="<<x<<", nelem[x]="<<nelem[x]<<"\n";
        if (nelem[x]==1) {
            continue;
        }
        if (nelem[x]<minp) {
            minp = nelem[x]; vconstr.clear();
        }
        if (nelem[x]==minp) {
            vconstr.push_back(i);
        }
    }
    assert(vconstr.size()!=0);
    vector<ll> vans(N,0);
    for (ll x: vconstr) {
        vans[x]=1;
    }
    return vans;
}


vector<int> find_reachable_slow(vector<int> r, vector<int> u, vector<int> v, vector<int> c) {
    ll N = r.size(); ll M = u.size();
    ll ans[N];
    map<ll,vector<ll>> mf;
    for (ll i=0;i<N;i++) {
        set<ll> s0;
        s0.insert(i);
        set<ll> s1;
        s1.insert(r[i]);
        for (ll T=0;T<M;T++) {
            for (ll j=0;j<M;j++) {
                if (s1.find(c[j])!=s1.end()) {
                    if (s0.find(u[j])!=s0.end() || s0.find(v[j])!=s0.end()) {
                        s0.insert(u[j]);
                        s0.insert(v[j]);
                        s1.insert(r[u[j]]);
                        s1.insert(r[v[j]]);
                    }
                }
            }
        }
        ans[i]=s0.size();
        mf[ans[i]].push_back(i);
    }
    vector<ll> vc = (*(mf.begin())).second;
    vector<ll> fans(N,0);
    for (ll x: vc) {
        fans[x]=1;
    }
    return fans;
}

vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) {
    return find_reachable_slow(r,u,v,c);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...