Submission #470695

#TimeUsernameProblemLanguageResultExecution timeMemory
470695TentacleslaveKeys (IOI21_keys)C++17
0 / 100
1 ms204 KiB
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

int increment, total_size;
vector<int> scc_value;
vector<int> mutex;

int dfs(int v, const vector<int>& vertex, const vector<vector<pair<int, int>>>& edge_table) {
    if(mutex[v] == 1)
        return scc_value[v];
    
    if(mutex[v] == 2)
        return -1;

    mutex[v] = 1;
    
    int min = increment;
    
    scc_value[v] = min;
    
    increment++;
    
    for(auto i : edge_table[v]) {
        if(vertex[v] != i.second) continue;
        int fetch = dfs(i.first, vertex, edge_table);
        if(min > fetch && fetch != -1)
            min = fetch;
    }
    
    scc_value[v] = min;
    
    mutex[v] = 2;
    
    return min;
}

vector<int> find_components(const vector<int>& vertex, const vector<vector<pair<int, int>>>& edge_table) {
    
    increment = 0;
    scc_value.resize(vertex.size());
    mutex.resize(vertex.size());
  
    fill (scc_value.begin(), scc_value.end(), 0);
    fill (mutex.begin(), mutex.end(), 0);
    for(vector<int>::const_iterator i = vertex.begin(); i != vertex.end(); i++)
        dfs(i - vertex.begin(), vertex, edge_table);
    
    return scc_value;
}

// vertex weighted by (key, list of subvertex), edge weighted by (connector's key id)
vector<int> find_reachable_internal(vector<pair<int, vector<int>>> vertex, vector<vector<pair<int, int>>> edge_table) {
    vector<int> simple_vertex;
    for(auto i : vertex)
        simple_vertex.push_back(i.first);
  	vector<int> scc_table = find_components(simple_vertex, edge_table);

	// To-do: construct new graph consists of SCC
    // Required: mapping vertex to SCC number ... vertex (--- scc_table --->) (--- scc_map --->) new_vertex
    // Do not fetch: for all SCC, size = 1
    
    vector<int> reverse_map = scc_table;
    std::sort(reverse_map.begin(), reverse_map.end());
    reverse_map.erase(unique(reverse_map.begin(), reverse_map.end()), reverse_map.end());
    
    if(reverse_map.size() == vertex.size()) {
        int min_size = 1e9;
        for(auto i : vertex) {
            bool res = false;
            for(auto j : edge_table[i.first]) {
                if(i.first == j.second)
                    res = true;
            }
            if(res) i.second.clear();
            if(min_size > i.second.size() && i.second.size() > 0)
                min_size = i.second.size();
        }
        vector<int> restored_vertex;
        restored_vertex.resize(total_size, 0);
        for(auto i : vertex) {
            for(auto j : i.second) {
                if(i.second.size() == min_size)
                    restored_vertex[j] = 0;
                else
                    restored_vertex[j] = 1;
            }
        }
        return restored_vertex;
    }
    
    // To-do: Query
    
    vector<int> scc_map;
    scc_map.resize(vertex.size(), 0);
    
    for(vector<int>::iterator i = reverse_map.begin(); i != reverse_map.end(); i++)
        scc_map[*i] = i - reverse_map.begin();
    
    vector<pair<int, vector<int>>> new_vertex;
    
    new_vertex.resize(reverse_map.size(), {0, {}});
    
    for(auto i = new_vertex.begin(); i != new_vertex.end(); i++) {
        i->first = i - new_vertex.begin();
    }
    
    for(vector<pair<int, vector<int>>>::const_iterator i = vertex.begin(); i != vertex.end(); i++) {
        int pos = i - vertex.begin();
        for(auto j : i->second)
     	    new_vertex[scc_map[scc_table[pos]]].second.push_back(j);
    }
    
    vector<vector<pair<int, int>>> new_edge_table;
    
    new_edge_table.resize(reverse_map.size(), {});
    
    for(vector<vector<pair<int, int>>>::const_iterator i = edge_table.begin(); i != edge_table.end(); i++) {
        int arg1 = scc_map[scc_table[i - edge_table.begin()]];
        for(auto j : *i) {
            int arg2 = scc_map[scc_table[j.first]];
        	int arg3 = scc_map[scc_table[j.second]];
            new_edge_table[arg1].push_back({arg2, arg3});
        }
    }
	
  	return find_reachable_internal(new_vertex, new_edge_table);
}

vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) {
    total_size = r.size();
    int edge_size = u.size();
    
    vector<pair<int, vector<int>>> vertex;
    vector<vector<pair<int, int>>> edge_table;
    
    for(int i = 0; i < total_size; i++) {
        vertex.push_back({r[i], {i}});
    }
    edge_table.resize(vertex.size(), {});
    
    for(auto i = u.begin(), j = v.begin(), k = c.begin(); i != u.end() && j != v.end() && k != c.end(); i++, j++, k++) {
        edge_table[*i].push_back({*j, *k});
        edge_table[*j].push_back({*i, *k});
    }
    
    return find_reachable_internal(vertex, edge_table);
}

Compilation message (stderr)

keys.cpp: In function 'std::vector<int> find_reachable_internal(std::vector<std::pair<int, std::vector<int> > >, std::vector<std::vector<std::pair<int, int> > >)':
keys.cpp:57:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
   57 |     for(auto i : vertex)
      |     ^~~
keys.cpp:59:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
   59 |    vector<int> scc_table = find_components(simple_vertex, edge_table);
      |    ^~~~~~
keys.cpp:78:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   78 |             if(min_size > i.second.size() && i.second.size() > 0)
      |                ~~~~~~~~~^~~~~~~~~~~~~~~~~
keys.cpp:85:36: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   85 |                 if(i.second.size() == min_size)
      |                    ~~~~~~~~~~~~~~~~^~~~~~~~~~~
keys.cpp: In function 'std::vector<int> find_reachable(std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
keys.cpp:134:9: warning: unused variable 'edge_size' [-Wunused-variable]
  134 |     int edge_size = u.size();
      |         ^~~~~~~~~
#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...