Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <iomanip>
- #include <vector>
- #include <map>
- #include <string>
- #include <cstring>
- #include <set>
- #include <queue>
- #include <stack>
- #include <bitset>
- #include <algorithm>
- #include <cstdio>
- #include <cstdlib>
- #include <cmath>
- using namespace std;
- #define MAXN 5010
- #define ap(a1, an, n) (((a1) + (an)) * (n) / 2)
- long long C [MAXN + 10][15];
- long long n, m, vh[5000], ans;
- vector < vector <long long> > g;
- long long dsu_parent[MAXN + 10], dsu_rank[MAXN + 10], dsu_vert[MAXN + 10], dsu_edge[MAXN + 10];
- set <long long> all_cmp;
- void make_set (long long v)
- {
- dsu_parent[v] = v;
- dsu_rank[v] = 0;
- }
- long long find_set (long long v)
- {
- if (v == dsu_parent[v])
- return v;
- return dsu_parent[v] = find_set (dsu_parent[v]);
- }
- long long union_sets (long long a, long long b)
- {
- a = find_set (a);
- b = find_set (b);
- if (a != b)
- {
- if (dsu_rank[a] < dsu_rank[b])
- swap (a, b);
- dsu_parent[b] = a;
- dsu_vert[a] += dsu_vert[b];
- dsu_edge[a] += dsu_edge[b];
- all_cmp.erase(b);
- if (dsu_rank[a] == dsu_rank[b])
- dsu_rank[a]++;
- }
- return a;
- }
- int main()
- {
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- long long i, ii, j, u, v, mn3, mn4, uc, vc, k, ps[MAXN], ca[MAXN];
- vector <long long> ins;
- vector <long long> :: iterator it, ite, itu;
- set <long long> :: iterator sit;
- for (i = 1; i <= MAXN; i++)
- {
- C[i][0] = C[i][i] = 1;
- for (j = 1; j < 10; j++)
- C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
- }
- //////////////////// PREPARING OVER /////////////////////
- cin >> n >> m;
- ans = n + n * (n - 1) / 2 + C[n+1][3] + C[n+1][4];
- g.resize(n);
- for (i = 0; i < n; i++)
- {
- make_set (i);
- dsu_vert[i] = 1;
- all_cmp.insert(i);
- }
- for (ii = 0; ii < m; ii++)
- {
- cin >> u >> v;
- u--, v--;
- ans--;
- ///////////////////////// 3 /////////////////////////
- mn3 = n - 2 - (g[u].size() + g[v].size());
- sort(g[u].begin(), g[u].end());
- sort(g[v].begin(), g[v].end());
- ins.resize(g[u].size() + g[v].size());
- it = set_intersection (g[u].begin(), g[u].end(), g[v].begin(), g[v].end(), ins.begin());
- mn3 += long long (it - ins.begin());
- ///////////////////////// 4 /////////////////////////
- uc = find_set(u); vc = find_set(v);
- for (i = 0; i < MAXN; i++)
- ps[i] = 0, ca[i] = 0;
- mn4 = 0;
- i = 0;
- for (sit = all_cmp.begin(); sit != all_cmp.end(); sit++, i++)
- {
- if (i)
- ps[i] += ps[i - 1];
- long long cur = *sit;
- if (cur != uc && cur != vc)
- {
- ps[i] += dsu_vert[cur];
- ca[i] = dsu_vert[cur];
- mn4 += (dsu_vert[cur] * (dsu_vert[cur] - 1)) / 2 - dsu_edge[cur];
- }
- }
- k = all_cmp.size();
- for (i = 0; i < k; i++)
- {
- long long cur_part_sum = 0;
- cur_part_sum = ps[k - 1];
- cur_part_sum -= ps[i];
- mn4 += ca[i] * cur_part_sum;
- }
- if (uc != vc)
- {
- long long soc_u = dsu_vert[uc], soc_v = dsu_vert[vc], eoc_u = dsu_edge[uc], eoc_v = dsu_edge[vc], k1 = g[u].size(), k2 = g[v].size();
- bool B1[MAXN] = {}, B2[MAXN] = {};
- long long bad_edges = 0, sum_of_steps = 0, novalid_empty_edges = 0;
- B1[u] = true;
- sum_of_steps += k1;
- bad_edges += k1;
- for (i = 0; i < k1; i++)
- {
- B1[g[u][i]] = true;
- sum_of_steps += g[g[u][i]].size();
- }
- for (i = 0; i < g[u].size(); i++)
- for (j = 0; j < g[g[u][i]].size(); j++)
- if (B1[g[g[u][i]][j]])
- bad_edges++;
- bad_edges >>= 1;
- sum_of_steps -= bad_edges;
- novalid_empty_edges = ap(soc_u - 1, soc_u - 1 - k1, (soc_u - 1) - (soc_u - 1 - k1) + 1) - sum_of_steps;
- mn4 += (soc_u * (soc_u - 1)) / 2 - eoc_u - novalid_empty_edges;
- bad_edges = sum_of_steps = 0;
- B2[v] = true;
- sum_of_steps += k2;
- bad_edges += k2;
- for (i = 0; i < g[v].size(); i++)
- {
- B2[g[v][i]] = true;
- sum_of_steps += g[g[v][i]].size();
- }
- for (i = 0; i < g[v].size(); i++)
- for (j = 0; j < g[g[v][i]].size(); j++)
- if (B2[g[g[v][i]][j]])
- bad_edges++;
- bad_edges >>= 1;
- sum_of_steps -= bad_edges;
- novalid_empty_edges = ap(soc_v - 1, soc_v - 1 - k2, (soc_v - 1) - (soc_v - 1 - k2) + 1) - sum_of_steps;
- mn4 += (soc_v * (soc_v - 1)) / 2 - eoc_v - novalid_empty_edges;
- mn4 += (soc_u - 1 - k1) * (soc_v - 1 - k2);
- for (i = 0; i < k; i++)
- mn4 += (soc_u - 1 - k1) * ca[i] + (soc_v - 1 - k2) * ca[i];
- }
- else
- {
- long long soc = dsu_vert[uc], eoc = dsu_edge[vc], k1 = g[u].size(), k2 = g[v].size();
- vector <long long> intersect_of_lists(g[u].size() + g[v].size());
- vector <long long> union_of_lists(g[u].size() + g[v].size());
- ite = set_intersection(g[u].begin(), g[u].end(), g[v].begin(), g[v].end(), intersect_of_lists.begin());
- itu = set_union(g[u].begin(), g[u].end(), g[v].begin(), g[v].end(), union_of_lists.begin());
- long long ke = ite - intersect_of_lists.begin(), ku = itu - union_of_lists.begin();
- intersect_of_lists.resize(ke);
- union_of_lists.resize(ku);
- bool B[5001] = {};
- long long bad_edges = 0, sum_of_steps = 0, novalid_empty_edges = 0;
- B[v] = true;
- B[u] = true;
- sum_of_steps += k1 + k2;
- bad_edges += k1 + k2;
- for (i = 0; i < ku; i++)
- {
- B[union_of_lists[i]] = true;
- sum_of_steps += g[union_of_lists[i]].size();
- }
- for (i = 0; i < ku; i++)
- for (j = 0; j < g[union_of_lists[i]].size(); j++)
- if (B[g[union_of_lists[i]][j]]) bad_edges++;
- bad_edges /= 2;
- sum_of_steps -= bad_edges;
- novalid_empty_edges = ap(soc - 1, soc - 2 - ku, (soc - 1) - (soc - 2 - ku) + 1) - sum_of_steps;
- mn4 += (soc * (soc - 1)) / 2 - eoc - novalid_empty_edges;
- for (i = 0; i < k; i++)
- mn4 += (soc - 2 - ku) * ca[i];
- }
- ///////////////////////// M /////////////////////////
- ans -= mn3 + mn4;
- g[u].push_back(v);
- g[v].push_back(u);
- dsu_edge[union_sets(u, v)]++;
- }
- cout << ans;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement