// Source: https://oj.uz/problem/view/JOI20_joitter2
//
#include "bits/stdc++.h"
using namespace std;
#define s second
#define f first
#define pb push_back
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef vector<int> vi;
#define FOR(i, a, b) for (int i = (a); i<b; i++)
bool ckmin(int& a, int b){ return b < a ? a = b, true : false; }
bool ckmax(int& a, int b){ return b > a ? a = b, true : false; }
const int N = 1e5 + 10;
set<int> in[N], group[N], comp[N]; // out is the set of outgoing people and ingoing followers
vi p(N,- 1);
long long res = 0;
int p2(int x) {
return x * (x-1);
}
int get(int x) {
return p[x] < 0 ? x : p[x] = get(p[x]);
}
void unite(int a, int b) {
a = get(a);b=get(b);
if (a==b) return;
// cout << a << in[a].size() << endl;
res -= p2(-p[a]) + p2(-p[b]) + (-p[a]) * (in[a].size()) + (-p[b]) * in[b].size();
// cout << res << endl;
if (-p[a] > -p[b]) {
// swap(in[a], in[b]);
// swap(out[a], out[b]);
swap(a, b);
}
// cout << res << endl;
// if (in[a].size() > in[b].size()) swap(in[a], in[b]);
// if (out[a].size() > out[b].size()) swap(out[a], out[b]);
p[b] += p[a];
p[a]=b;
for (auto x: group[a]) {
if (in[b].count(x)) in[b].erase(x);
group[b].insert(x);
}
set<int> future_merge;
for (auto x: in[a]) {
int xx = get(x);
if (in[xx].find(b) != in[xx].end()) future_merge.insert(xx);
if (get(x) != b) {
in[b].insert(x);
comp[b].insert(get(x));
}
}
// out[b].erase(a);
// out[a].erase(b);
// set<int> future_merge;
// for (auto x: in[a]) {
// if (get(x) == b) continue;
// in[b].insert(x);
// if (out[b].find(x) != out[b].end())
// future_merge.insert(x);
// out[x].erase(a);
// out[x].insert(b);
// }
// for (auto x: out[a]) {
// out[b].insert(x);
// if (in[b].find(x) != in[b].end())
// future_merge.insert(x);
// in[x].insert(b);
// }
// cout << -p[b] << endl;
res += p2(-p[b]) + (-p[b]) * in[b].size();
for (auto x: future_merge) unite(x, b);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
FOR(i,1,n+1) group[i].insert(i);
FOR(i, 0, m) {
int xx, yy;
cin >> xx >> yy;
int x=get(xx);
int y=get(yy);
// cout << x << y << endl;
if (x != y) {
if (in[y].count(xx) == 0) res+=-p[y];
in[y].insert(xx);
comp[y].insert(x);
// cout << y << xx << ' ' << x << endl;
if (comp[x].find(y) != comp[x].end()) unite(x, y);
}
cout << res << endl;
}
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |