Submission #1161575

#TimeUsernameProblemLanguageResultExecution timeMemory
1161575AvianshSwapping Cities (APIO20_swap)C++20
100 / 100
117 ms17072 KiB
#include "swap.h"

#include <bits/stdc++.h>

using namespace std;

struct dsu{
    vector<int>root;
    vector<int>siz;
    vector<int>valtime;
    vector<int>lastroot;
    vector<int>d;
    vector<vector<int>>g;
    int n;
    dsu(int nn){
        n=nn;
        root = vector<int>(n);
        iota(root.begin(),root.end(),0);
        siz=vector<int>(n,1);
        valtime = vector<int>(n,1e9);
        lastroot = vector<int>(n,-1);
        d=vector<int>(n);
        g=vector<vector<int>>(n);
    }
    void makeVal(int x, int tim){
        x=findRoot(x);
        valtime[x]=min(valtime[x],tim);
    }
    bool unite(int x, int y, int tim){
        x=findRoot(x);
        y=findRoot(y);
        //cout << "turned into " << x << " " << y << "\n";
        if(x==y){
            makeVal(x,tim);
            //cout << "cycle found\n";
            return 0;
        }
        if(siz[x]<siz[y]){
            //cout << "swapped\n";
            swap(x,y);
        }
        //x is greater now
        lastroot[y]=tim;
        //as soon as timth edge was added y ceased to be root so this is non inclusive
        siz[x]+=siz[y];
        root[y]=x;
        if(valtime[y]<1e9){
            //if y comp is valid then x is also now valid
            //cout << y << " was valid\n";
            makeVal(x,tim);
        }
        return 1;
    }
    int findRoot(int x){
        if(x==root[x]){
            return x;
        }
        return findRoot(root[x]);
    }

    void dfs(int st, int dep, int p){
        d[st]=dep;
        for(int i : g[st]){
            if(i==p){
                continue;
            }
            dfs(i,dep+1,st);
        }
    }

    void pre(){
        //ok so all should be connected now and must do precomp for depth and all
        int r = findRoot(0);
        //all god is root now so depth 0
        //first it is time to make the tree
        for(int i = 0;i<n;i++){
            if(i==r)
                continue;
            g[i].push_back(root[i]);
            g[root[i]].push_back(i);
        }
        //tree made now dfs
        dfs(r,0,-1);
        //ok so depths done which means pre over now must make main thingy
    }

    int bestTime(int x, int y){
        //TODO: will make corner case for -1s
        if(d[x]<d[y]){
            swap(x,y);
        }
        int ans = -1;
        while(d[x]>d[y]){
            ans=max(ans,lastroot[x]);
            x=root[x];
        }
        //ok now both at same depth
        while(x!=y){
            ans=max(ans,lastroot[x]);
            ans=max(ans,lastroot[y]);
            x=root[x];
            y=root[y];
        }
        //ok now minimum time for them to be connected is here now minimum time for validity is to be discovered
        //will only make x go up now
        while(valtime[x]==1e9){
            ans=max(ans,lastroot[x]);
            x=root[x];
        }
        //ok so now it should be valid so just max
        ans=max(ans,valtime[x]);
        return ans;
    }
};

vector<array<int,3>>edges;
int n,m;
bool val = 1;
dsu ds(1e5+5);
void init(int N, int M, vector<int> U, vector<int> V, vector<int> W) {
    n=N;
    m=M;
    for(int i = 0;i<m;i++){
        edges.push_back({W[i],U[i],V[i]});
    }
    sort(edges.begin(),edges.end());
    int d[n];
    fill(d,d+n,0);
    for(int i = 0;i<m;i++){
        int a = edges[i][1];
        int b = edges[i][2];
        //cout << "uniting " << a << " " << b << "\n";
        ds.unite(a,b,i);
        //cout << "united " << a << " " << b << "\n";
        d[a]++;
        d[b]++;
        if(d[a]>=3||d[b]>=3){
            ds.makeVal(a,i);
        }
    }
    ds.pre();
    val=(ds.valtime[ds.findRoot(0)]!=1e9);
}

int getMinimumFuelCapacity(int x, int y) {
    if(!val)
        return -1;
    return edges[ds.bestTime(x,y)][0];
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...