Submission #767194

# Submission time Handle Problem Language Result Execution time Memory
767194 2023-06-26T13:44:07 Z danikoynov Simurgh (IOI17_simurgh) C++14
0 / 100
1 ms 340 KB
#include "simurgh.h"
#include <bits/stdc++.h>

using namespace std;

const int maxn = 510;
struct disjoint_set_union
{
    int par[maxn];

    disjoint_set_union() {};

    disjoint_set_union(int n)
    {
        for (int i = 0; i < n; i ++)
            par[i] = i;
    }

    int find_leader(int v)
    {
        if (v == par[v])
            return v;
        return (par[v] = find_leader(par[v]));
    }

    bool is_connected(int v, int u)
    {
        return find_leader(v) == find_leader(u);
    }

    void unite(int v, int u)
    {
        v = find_leader(v);
        u = find_leader(u);
        if (v == u)
            return;
        par[v] = u;
    }
};

int is_bridge[maxn * maxn];
int direction[maxn * maxn];
vector < pair < int, int > > adj[maxn];
int par[maxn], par_idx[maxn], used[maxn];
int depth[maxn];
void dfs(int v)
{
    used[v] = 1;
    for (pair < int, int > nb : adj[v])
    {
        if (nb.first == par[v])
            continue;
        if (!used[nb.first])
        {
            par_idx[nb.first] = nb.second;
            par[nb.first] = v;
            direction[nb.second] = 1;
            depth[nb.first] = depth[v] + 1;
            dfs(nb.first);
        }
        else
        {
            direction[nb.second] = -1;
        }
    }
}

vector < vector < int > > cycles;
vector < int > gold;
int visit[maxn * maxn], is_gold[maxn * maxn];
vector < int > span;
vector < int > tree;
void trav(int v)
{
    for (pair < int, int > nb : adj[v])
    {
        if (used[nb.first] == 0)
        {
            used[nb.first] = 1;
            tree.push_back(nb.second);
            trav(nb.first);
        }
    }
}


int N, M;
pair < int, int > ed[maxn * maxn];
vector < int > out[maxn];
int delta_gold(vector < int > edges)
{
    vector < int > res;
    res = edges;
    disjoint_set_union dsu(N);
    for (int i = 0; i < edges.size(); i ++)
        dsu.unite(ed[edges[i]].first, ed[edges[i]].second);


    int new_gold = 0;
    for (int i = 0; i < edges.size(); i ++)
        if (is_gold[edges[i]] == 1)
            new_gold --;
    for (int i = 0; i < span.size(); i ++)
    {
        int idx = span[i];
        int v = ed[idx].first, u = ed[idx].second;
        if (!dsu.is_connected(v, u))
        {
            dsu.unite(v, u);
            if (is_gold[idx] == 1)
            {
                ///cout << "--- " << v << " " << u << endl;
                new_gold --;
            }
            res.push_back(idx);
        }
    }
    ///cout << "delta" << endl;
    for (int i = 0; i < res.size(); i ++)
    {
        int idx = res[i];
        ///cout << ed[idx].first << " -- " << ed[idx].second << endl;
    }
    ///cout << new_gold << endl;
    new_gold = new_gold + count_common_roads(res);
    return new_gold;
}

int deg[maxn];
vector<int> find_roads(int n, vector<int> u, vector<int> v)
{
    int m = u.size();
    N = n;
    M = m;
    for (int i = 0; i < m; i ++)
    {
        ed[i] = {u[i], v[i]};
    }
    for (int i = 0; i < m; i ++)
    {
        adj[u[i]].push_back({v[i], i});
        adj[v[i]].push_back({u[i], i});
    }

    par[0] = -1;
    par_idx[0] = -1;
    dfs(0);

    for (int i = 0; i < m; i ++)
    {
        int V = u[i], U = v[i];
        if (direction[i] == -1)
        {
            if (depth[V] < depth[U])
                swap(V, U);
            vector < int > cycle;
            int cur = V;
            while(cur != U)
            {
                visit[par_idx[cur]] = 1;
                cycle.push_back(par_idx[cur]);
                cur = par[cur];

            }
            visit[i] = 1;
            cycle.push_back(i);
            cycles.push_back(cycle);
        }
    }
    /**cout << "--------------" << endl;
    for (int i = 0; i < m; i ++)
    {
        if (direction[i] == 1)
            cout << u[i] << " : " << v[i] << endl;
    }
    cout << "-------------" << endl;*/
    for (int i = 0; i < m; i ++)
    {
        if (!visit[i])
        {
            gold.push_back(i);
            span.push_back(i);
            is_gold[i] = 1;
        }
        else
        {
            if (direction[i] == 1)
                span.push_back(i);
        }
    }

    for (vector < int > cycle : cycles)
    {
        for (int i = 0; i < n; i ++)
            used[i] = 0;

        bool need = false;
        int mx = -1;
        for (int i = 0; i < cycle.size() - 1; i ++)
        {
            int edge = cycle[i];
            if (is_gold[edge] == 0)
                need = true;
            else
                mx = edge;
            used[v[edge]] = used[u[edge]] = 2;
        }

        if (!need)
            continue;


        tree.clear();
        for (int i = 0; i < n; i ++)
        {
            if (used[i] == 2)
                trav(i);
        }

        if (mx == -1)
        {

            vector < int > values;
            int max_val = -1, min_val = 1e9;
            for (int i = 0; i < cycle.size(); i ++)
            {
                vector < int > res = tree;
                for (int j = 0; j < cycle.size(); j ++)
                {
                    if (i != j)
                        res.push_back(cycle[j]);
                }
                values.push_back(count_common_roads(res));
                max_val = max(max_val, values.back());
                min_val = min(min_val, values.back());
            }

            if (max_val == min_val)
            {
                for (int idx : cycle)
                    is_gold[idx] = -1;
            }
            else
            {
                for (int i = 0; i < cycle.size(); i ++)
                {
                    if (values[i] == min_val)
                        is_gold[cycle[i]] = 1;
                    else
                        is_gold[cycle[i]] = -1;
                }
            }
        }
        else
        {
             /**           cout << "base" << endl;
            for (int i = 0; i < cycle.size(); i ++)
            {
                int idx = cycle[i];
                cout << u[idx] << " " << v[idx] << endl;
            }*/

            int max_val = 0, min_val = 1e9;
            vector < int > res = tree;
            for (int i = 0; i < cycle.size(); i ++)
                if (i != mx)
                    res.push_back(cycle[i]);

            int val = count_common_roads(res);
            if (is_gold[cycle[mx]] == 1)
            {
                min_val = val;
                max_val = val + 1;
            }
            else
            {
                min_val = val - 1;
                max_val = val;
            }

            for (int i = 0; i < cycle.size() - 1; i ++)
            {
                if (is_gold[cycle[i]] == 0)
                {
                    res = tree;
                    for (int j = 0; j < cycle.size(); j ++)
                        if (j != i)
                            res.push_back(cycle[j]);
                    val = count_common_roads(res);
                    if (val == max_val)
                        is_gold[cycle[i]] = -1;
                    else
                        is_gold[cycle[i]] = 1;
                }
            }
        }
    }

    queue < int > q;
    for (int i = 0; i < n; i ++)
    {

        for (int j = 0; j < m; j ++)
        {
            if (v[j] == i || u[j] == i)
                out[i].push_back(j);
        }

        deg[i] = delta_gold(out[i]);
        if (deg[i] == 1)
            q.push(i);
    }

    /**cout << "Span" << endl;
    for (int i = 0; i < span.size(); i ++)
    {
        int idx = span[i];
        cout << u[idx] << " : " << v[idx] << " " << is_gold[idx] << endl;
    }*/
    //cout << delta_gold(out[1]) << endl;
    //exit(0);
    while(!q.empty())
    {
        int cur = q.front();
        q.pop();
        if (deg[cur] == 0)
            continue;
        int l = 0, r = out[cur].size() - 1;
        while(l <= r)
        {
            int m = (l + r) / 2;
            vector < int > st;
            for (int i = 0; i <= m; i ++)
                st.push_back(out[cur][i]);
            if (delta_gold(st) > 0)
                r = m - 1;
            else
                l = m + 1;
        }
        is_gold[out[cur][l]] = 1;
        int oth = u[out[cur][l]];
        if (oth == cur)
            oth = v[out[cur][l]];
        deg[oth] --;
        deg[cur] --;
        if (deg[oth] == 1)
            q.push(oth);
    }

    vector < int > ans;
    for (int i = 0; i < m; i ++)
        if (is_gold[i] == 1)
            ans.push_back(i);
    return ans;

}

Compilation message

simurgh.cpp: In function 'int delta_gold(std::vector<int>)':
simurgh.cpp:95:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   95 |     for (int i = 0; i < edges.size(); i ++)
      |                     ~~^~~~~~~~~~~~~~
simurgh.cpp:100:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  100 |     for (int i = 0; i < edges.size(); i ++)
      |                     ~~^~~~~~~~~~~~~~
simurgh.cpp:103:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  103 |     for (int i = 0; i < span.size(); i ++)
      |                     ~~^~~~~~~~~~~~~
simurgh.cpp:119:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  119 |     for (int i = 0; i < res.size(); i ++)
      |                     ~~^~~~~~~~~~~~
simurgh.cpp:121:13: warning: unused variable 'idx' [-Wunused-variable]
  121 |         int idx = res[i];
      |             ^~~
simurgh.cpp: In function 'std::vector<int> find_roads(int, std::vector<int>, std::vector<int>)':
simurgh.cpp:199:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  199 |         for (int i = 0; i < cycle.size() - 1; i ++)
      |                         ~~^~~~~~~~~~~~~~~~~~
simurgh.cpp:225:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  225 |             for (int i = 0; i < cycle.size(); i ++)
      |                             ~~^~~~~~~~~~~~~~
simurgh.cpp:228:35: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  228 |                 for (int j = 0; j < cycle.size(); j ++)
      |                                 ~~^~~~~~~~~~~~~~
simurgh.cpp:245:35: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  245 |                 for (int i = 0; i < cycle.size(); i ++)
      |                                 ~~^~~~~~~~~~~~~~
simurgh.cpp:265:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  265 |             for (int i = 0; i < cycle.size(); i ++)
      |                             ~~^~~~~~~~~~~~~~
simurgh.cpp:281:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  281 |             for (int i = 0; i < cycle.size() - 1; i ++)
      |                             ~~^~~~~~~~~~~~~~~~~~
simurgh.cpp:286:39: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  286 |                     for (int j = 0; j < cycle.size(); j ++)
      |                                     ~~^~~~~~~~~~~~~~
simurgh.cpp:263:30: warning: variable 'min_val' set but not used [-Wunused-but-set-variable]
  263 |             int max_val = 0, min_val = 1e9;
      |                              ^~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 1 ms 340 KB correct
2 Incorrect 1 ms 340 KB WA in grader: NO
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 340 KB correct
2 Incorrect 1 ms 340 KB WA in grader: NO
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 340 KB correct
2 Incorrect 1 ms 340 KB WA in grader: NO
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 340 KB correct
2 Incorrect 0 ms 340 KB WA in grader: NO
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 340 KB correct
2 Incorrect 1 ms 340 KB WA in grader: NO
3 Halted 0 ms 0 KB -