Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <set>
- using namespace std;
- long long n,m;
- vector <vector <int> > G;
- vector <pair<int,int> > M;
- int dsu_parent[5000];
- int dsu_rank[5000];
- int size_of_component[5000];
- int edges_of_component[5000];
- set <int> all_components;
- long long C[5001][5001];
- long long answer_one=0,answer_two=0,answer_three=0,answer_four=0;
- long long real_answer=0;
- int MAXN=5000;
- ostream & operator<<(ostream &stream, vector <int> &A){
- for (int i=0;i<A.size();i++)
- cout<<A[i]<<" ";
- return stream;
- }
- int dsu_make(int i){
- dsu_parent[i]=i;
- dsu_rank[i]=0;
- }
- void pascal_init(){
- for (int i=0;i<=n;i++)
- C[i][i]=1,C[i][1]=i;
- for (int i=2;i<=n;i++)
- for (int j=2;j<=n-1;j++){
- C[i][j]=C[i-1][j-1]+C[i-1][j];
- //cout<<C[i][j]<<" "<<endl;
- }
- real_answer=C[n][1]+C[n][2]+C[n][3]+C[n][4];
- }
- int dsu_find(int i){
- if (i==dsu_parent[i])
- return i;
- return dsu_parent[i]=dsu_find(dsu_parent[i]);
- }
- void dsu_unite(int a, int b){
- a=dsu_find(a);
- b=dsu_find(b);
- if (a!=b){
- if (dsu_rank[a]<dsu_rank[b])
- swap(a,b);
- dsu_parent[b]=a;
- size_of_component[a]+=size_of_component[b];
- edges_of_component[a]+=edges_of_component[b];
- all_components.erase(b);
- if (dsu_rank[a]==dsu_rank[b])
- dsu_rank[a]++;
- }
- }
- void iterat_for_three(int numb){
- //cout<<"ENTEROFTHREE"<<endl;
- int u=M[numb].first; int v=M[numb].second;
- long long k1=G[u].size();
- long long k2=G[v].size();
- sort (G[u].begin(),G[u].end());
- sort (G[v].begin(),G[v].end());
- vector<int> intersect_of_lists(G[u].size()+G[v].size());
- vector<int>::iterator ite=set_intersection(G[u].begin(),G[u].end(),G[v].begin(),G[v].end(),intersect_of_lists.begin());
- long long e=ite-intersect_of_lists.begin();
- long long answer=(n-2)-k1-k2+e;
- answer_three+=answer;
- //cout<<"EXITOFTHREE"<<endl;
- }
- void iterat_for_four(int numb){
- //cout<<"ENTER:"<<endl;
- int u=M[numb].first; int v=M[numb].second;
- int u_comp=dsu_find(u); int v_comp=dsu_find(v);
- long long k1=G[u].size();
- long long k2=G[v].size();
- long long answer=0;
- long long k=all_components.size();
- long long sums[5000];
- long long local_sizes[5000];
- for (int j=0;j<5000;j++)
- sums[j]=0,local_sizes[j]=0;
- int i=0;
- for (set<int>::iterator it=all_components.begin();it!=all_components.end();it++,i++){
- int cur_comp=*it;
- if (i) sums[i]+=sums[i-1];
- if (cur_comp!=u_comp && cur_comp!=v_comp){
- sums[i]+=size_of_component[cur_comp];
- local_sizes[i]=size_of_component[cur_comp];
- int socp=size_of_component[cur_comp];
- answer+=(socp*(socp-1))/2-edges_of_component[cur_comp];
- }
- }
- //cout<<"POINT1:"<<answer<<endl;
- for (int i=0;i<k;i++){
- long long chast_sum=sums[k-1];
- chast_sum-=sums[i];
- //cout<<local_sizes[i]<<" ";
- answer+=local_sizes[i]*chast_sum;
- }
- //cout<<"POINT2:"<<answer<<endl;
- if (u_comp!=v_comp){
- long long dob=0;
- long long socp=size_of_component[u_comp];
- dob+=((socp-1-G[u].size())*(socp-2-G[u].size()))/2-(edges_of_component[u_comp]-G[u].size());
- socp=size_of_component[v_comp];
- dob+=((socp-1-G[v].size())*(socp-2-G[v].size()))/2-(edges_of_component[v_comp]-G[v].size());
- dob+=(size_of_component[u_comp]-1-G[u].size())*(size_of_component[v_comp]-1-G[v].size());
- for (int i=0;i<k;i++){
- //cout<<"i:"<<i<<" "<<local_sizes[i]<<" "<<size_of_component[u_comp]<<endl;
- answer+=(size_of_component[u_comp]-1-G[u].size())*local_sizes[i];
- }
- //cout<<"POINT2.7:"<<answer<<endl;
- for (int i=0;i<k;i++){
- answer+=(size_of_component[v_comp]-1-G[v].size())*local_sizes[i];
- }
- //cout<<"POINT3:"<<answer<<endl;
- }
- else{
- //cout<<"POINT4:"<<answer<<endl;
- sort (G[u].begin(),G[u].end());
- sort (G[v].begin(),G[v].end());
- vector<int> intersect_of_lists(G[u].size()+G[v].size());
- vector<int>::iterator ite=set_intersection(G[u].begin(),G[u].end(),G[v].begin(),G[v].end(),intersect_of_lists.begin());
- intersect_of_lists.resize(ite-intersect_of_lists.begin());
- long long e=ite-intersect_of_lists.begin();
- int nn=size_of_component[u_comp];
- bool its_not_used[5000];
- its_not_used[u]=true; its_not_used[v]=true;
- for (int i=0;i<G[u].size();i++){
- its_not_used[G[u][i]]=true;
- }
- for (int i=0;i<G[v].size();i++){
- its_not_used[G[v][i]]=true;
- }
- int unrated_edges=0;
- for (int i=0;i<G[v].size();i++)
- for (int j=0;j<G[G[v][i]].size();j++){
- int to=G[G[v][i]][j];
- //cout<<"TO:"<<to+1<<endl;
- if (its_not_used[to])
- unrated_edges++;
- }
- for (int i=0;i<G[u].size();i++)
- for (int j=0;j<G[G[u][i]].size();j++){
- int to=G[G[u][i]][j];
- //cout<<"TO:"<<to+1<<endl;
- if (its_not_used[to])
- unrated_edges++;
- }
- for (int i=0;i<intersect_of_lists.size();i++)
- for (int j=0;j<G[intersect_of_lists[i]].size();j++){
- int to=G[intersect_of_lists[i]][j];
- //cout<<"TO:"<<to+1<<endl;
- if (its_not_used[to])
- unrated_edges--;
- }
- unrated_edges+=k1+k2;
- //cout<<unrated_edges<<endl;
- unrated_edges/=2;
- int k1=int(G[u].size());
- int k2=int(G[v].size());
- long long dob=(nn-3-k1-k2+e>=0 ? (nn-2-k1-k2+e)*(nn-3-k1-k2+e) : 0)-(edges_of_component[u_comp]-unrated_edges);
- if (dob<0) dob=0;
- answer+=dob;
- //cout<<"POINT5:"<<answer<<endl;
- for (int i=0;i<k;i++){
- answer+=(nn-2>=0 ? (nn-2-k1-k2+e) : 0)*local_sizes[i];
- }
- //cout<<"POINT6:"<<answer<<endl;
- }
- answer_four+=answer;
- dsu_unite(u,v);
- u_comp=dsu_find(u);
- G[u].push_back(v);
- G[v].push_back(u);
- edges_of_component[u_comp]++;
- //cout<<"EXIT"<<endl;
- }
- int main(){
- cin>>n>>m;
- G.resize(n);
- M.resize(m);
- answer_one=0; answer_two=m;
- for (int i=0;i<m;i++){
- int a,b; cin>>a>>b;
- a--; b--;
- if (a>b) swap(a,b);
- M[i]=(make_pair(a,b));
- }
- for (int i=0;i<n;i++){
- dsu_make(i);
- size_of_component[i]=1;
- all_components.insert(i);
- }
- for (int i=0;i<m;i++){
- iterat_for_three(i);
- iterat_for_four(i);
- }
- pascal_init();
- //cout<<C[n][4]-answer_four<<" "<<C[n][3]-answer_three<<" "<<real_answer<<endl;
- cout<<real_answer-answer_one-answer_two-answer_three-answer_four<<endl;
- return 0;
- }
Add Comment
Please, Sign In to add comment