# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
895881 | rukashii | Making Friends on Joitter is Fun (JOI20_joitter2) | C++17 | 5021 ms | 49756 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
#define file if (fopen("input.txt", "r")) { freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); }
#define int long long
#define f first
#define s second
void setIn(string s) { freopen(s.c_str(), "r", stdin); }
void setOut(string s) { freopen(s.c_str(), "w", stdout); }
void setIO(string s = "") {
if (s.size()) setIn(s+".inp"), setOut(s+".out");
}
const int maxn = 3e5 + 2;
int ans;
int n, m, a[maxn], b[maxn];
int lab[maxn], sz[maxn];
set <int> adj[maxn], radj[maxn], child[maxn];
vector <pair <int, int>> to_join;
int Get(int u)
{
return (lab[u] == -1) ? u : (lab[u] = Get(lab[u]));
}
void add_oneway_edge(int A, int B)
{
adj[A].insert(B);
radj[B].insert(A);
if (radj[A].count(B))
{
to_join.push_back({Get(A), Get(B)});
}
}
int get_size(int u)
{
return child[u].size() + adj[u].size() + radj[u].size();
}
void Merge(int u, int v)
{
if (u == v)
return;
// small to large, we merge v to u
if (get_size(u) < get_size(v))
swap(u, v);
// we already got the edge from sz[u] -> v
ans += sz[u] * child[v].size() + sz[v] * child[u].size();
lab[v] = u;
sz[u] += sz[v];
for (int p : child[v])
{
if (child[u].count(p))
{
ans -= sz[u];
}
else
child[u].insert(p);
}
adj[u].erase(v); adj[v].erase(u);
radj[u].erase(v); radj[v].erase(u);
for (int p : radj[v])
{
radj[u].insert(p);
add_oneway_edge(p, u);
}
for (int p : adj[v])
{
adj[u].insert(p);
add_oneway_edge(u, p);
}
}
signed main()
{
// setIO();
file;
ios::sync_with_stdio(0); cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cin >> a[i] >> b[i];
}
for (int i = 1; i <= n; i++)
{
lab[i] = -1; sz[i] = 1;
child[i].insert(i);
}
for (int i = 1; i <= m; i++)
{
int A = a[i], B = b[i];
// A -> B
if (Get(A) != Get(B) && !child[Get(B)].count(A))
{
child[Get(B)].insert(A);
ans += sz[Get(B)];
A = Get(A), B = Get(B);
add_oneway_edge(A, B);
while (to_join.size())
{
int X = to_join.back().f, Y = to_join.back().s;
Merge(X, Y);
to_join.pop_back();
}
}
cout << ans << '\n';
}
}
Compilation message (stderr)
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |