Submission #1149247

#TimeUsernameProblemLanguageResultExecution timeMemory
1149247Cauchico수천개의 섬 (IOI22_islands)C++17
19.25 / 100
45 ms6980 KiB
#include "islands.h"

#include <bits/stdc++.h>
using namespace std;


vector<int> c,d;
vector<bool> visited;
void dfs(int v, vector<vector<int>> const& adj, vector<int> &output) {
    visited[v] = true;
    for (auto u : adj[v])
        if (!visited[u])
            dfs(u, adj, output);
    output.push_back(v);
}
void scc(vector<vector<int>> const& adj, vector<vector<int>> &components, vector<vector<int>> &adj_cond) {
    int n = adj.size();
    components.clear(), adj_cond.clear();

    vector<int> order; // will be a sorted list of G's vertices by exit time

    visited.assign(n, false);

    // first series of depth first searches
    for (int i = 0; i < n; i++)
        if (!visited[i])
            dfs(i, adj, order);

    // create adjacency list of G^T
    vector<vector<int>> adj_rev(n);
    for (int v = 0; v < n; v++)
        for (int u : adj[v])
            adj_rev[u].push_back(v);

    visited.assign(n, false);
    reverse(order.begin(), order.end());

    vector<int> roots(n, 0); // gives the root vertex of a vertex's SCC

    // second series of depth first searches
    for (auto v : order)
        if (!visited[v]) {
            std::vector<int> component;
            dfs(v, adj_rev, component);
            components.push_back(component);
            int root = *min_element(begin(component), end(component));
            if (component.size() > 1) {
                c[root] = 1;
                for (auto u : component) {
                    d[u] = 1;
                }
            }
            for (auto u : component)
                roots[u] = root;
        }

    // add edges to condensation graph
    adj_cond.assign(n, {});
    for (int v = 0; v < n; v++)
        for (auto u : adj[v])
            if (roots[v] != roots[u])
                adj_cond[roots[v]].push_back(roots[u]);
}

/*void dfs3(int v, int p, vector<int>& used, vector<int>& skip, vector<vector<int>>& adj, bool& ans) {
    used[v] = 1;
    for (auto u : adj[v]) {
        if (skip[u]) continue;
        if (!used[u]) {
            dfs3(u,v,used,skip,adj,ans);
        } else if (u != p) ans = true;
    }
}*/

bool solvable(int v, vector<int>& comp, vector<vector<int>>& adj) {
    vector<int> used(adj.size(),1), skip(adj.size(),1);
    for (auto u: comp) {skip[u] = used[u] = 0;}
    bool ans = false;
    for (auto u: comp) {
        int cnt = (u == v);
        for (auto x : adj[u]) {
            if (!skip[x]) cnt++;
        }
        ans |= cnt > 2;
    }
    //dfs3(v,-1,used,skip,adj,ans);   
    return ans;
}

vector<int> vis,p;
void dfs1(int v, vector<vector<int>>& adj) {
    vis[v] = 1;
    for (auto u: adj[v]) {
        p[u] += 1;
        if (!vis[u]) {
            dfs1(u,adj);
        }
    }
}

vector<int> vis2, reach;
void dfs2(int v, vector<vector<int>>& adj) {
    vis2[v] = 1;
    if (d[v]) {
        reach[v] = 1;
        return;
    }
    for (auto u: adj[v]) {
        if (!vis[u]) dfs2(u,adj);
    }
}


variant<bool, vector<int>> find_journey(int N, int M, vector<int> U, vector<int> V) {
    vector<vector<int>> adj,cadj,comps;
    adj.resize(N); c.resize(N); vis.resize(N); p.resize(N); d.resize(N); vis2.resize(N); reach.resize(N);
    for (int i=0;i<M;i++) {
        adj[U[i]].push_back(V[i]);
    }
    scc(adj,comps,cadj);
    bool ans = false;
    //checks if two path to same node in scc
    dfs1(0,cadj);
    queue<int> q; vector<int> used(N);
    for (int i=0;i<N;i++) 
        if (p[i] > 1) {
            q.push(i);
            used[i] = true;
        }
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        for (int u : cadj[v]) {
            if (!used[u]) {
                used[u] = true;
                q.push(u);
            }
        }
    }
    for (int i=0;i<N;i++) {
        if (used[i] and c[i]) ans = true;
    }
    //checks if can reach scc in two places
    dfs2(0,adj);
    int cnt = 0;
    for (int i=0;i<N;i++) {
        cnt += reach[i];
    }
    if (cnt > 1) ans = true;
    //if neither then at most one is reachable
    if (ans == false and cnt == 1) {
        int node = 0;
        for (int i=0; i<N; i++) if (reach[i]) node = i;
        vector<int> comp;
        for (auto u: comps) {
            for (auto v: u) {
                if (v == node) comp = u;
            }
        }
        if (comp.size() > 2) ans = solvable(node,comp,adj);
        else {
            if (comp[0] != node) swap(comp[0],comp[1]);
            int nb = 0;
            for (auto u : adj[node]) if (u == comp[1]) nb++;
            ans = nb > 1;
        }
    }
    return ans;
}
#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...