Submission #235276

#TimeUsernameProblemLanguageResultExecution timeMemory
235276rajarshi_basuMaking Friends on Joitter is Fun (JOI20_joitter2)C++14
17 / 100
5072 ms69472 KiB
#include <stdio.h>     
#include <stdlib.h>    
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <queue>
#include <deque>
#include <iomanip>
#include <cmath>
#include <set>
#include <stack>
#include <map>
#include <unordered_map>

#define FOR(i,n) for(int i=0;i<n;i++)
#define FORE(i,a,b) for(int i=a;i<=b;i++)
#define ll long long 
#define ld long double
//#define int short
#define vi vector<int>
#define pb push_back
#define ff first
#define ss second
#define ii pair<int,int>
#define iii pair<int,ii>
#define pll pair<ll,ll>
#define plll pair<ll,pll>
#define mp make_pair
#define vv vector
#define endl '\n'

using namespace std;
const int MAXN = 1e5+5;
int D = 0;
int E = 0;
int F = 0;
int G = 0;
struct DSU{
	ll tot = 0;
	int parent[MAXN];
	set<int> incoming[MAXN];// individual nodes 
	set<int> incomingCliques[MAXN];
	set<int> sentTo[MAXN];
	set<int> allNodes[MAXN];
	ll sz[MAXN];
	DSU(){
		FOR(i,MAXN)parent[i] = i;
		FOR(i,MAXN)sz[i] = 1;
		FOR(i,MAXN)allNodes[i].insert(i);
	}
	int find(int a){
		if(a != parent[a])parent[a] = find(parent[a]);
		return parent[a];
	}
	bool isSame(int a,int b){
		return find(a) == find(b);
	}
	// outgoing[e] = {a,i} means there are i edges going from Supernodes e to a
	// we only keep track of outgoing edges + internal clique edges;


	inline void addEdge(int a,int b){
		b = find(b);
		incomingCliques[b].insert(find(a));
		incoming[b].insert(a);
		sentTo[find(a)].insert(b);
		tot += sz[b];
	}

	void makeParent(int pa,int pb,set<int>& allIncomers){
		// make pa parent
		for(auto e : incoming[pa]){
			if(find(e) != pb)
				allIncomers.insert(e);
			tot -= sz[pa];
		}
		for(auto e : incoming[pb]){
			if(find(e) != pa)
				allIncomers.insert(e);
			tot -=sz[pb];
		}
		//for(auto x: allNodes[pb]){
			vi lst;
			for(auto e : sentTo[pb]){
				if(find(e) == pa){
					lst.pb(e);continue;
				}
				incomingCliques[e].erase(pb);
				incomingCliques[e].insert(pa);
			}
			for(auto e: lst)sentTo[pb].erase(e);
		//}

			


		incoming[pa].clear();
		incoming[pb].clear();
		incomingCliques[pa].clear();
		incomingCliques[pb].clear();
		//sentTo[pa].clear();
		//sentTo[pb].clear();


	}


	void merge(int a,int b){
		int pa = find(a);
		int pb = find(b);
		tot += 2*sz[pa]*sz[pb]; // new internal edges of the clique.
		//allIncomers.clear();
		//cout << "COMBINING: " << pa << " " << pb << endl;
		if(sz[pa] < sz[pb])swap(pa,pb);
		for(auto x : sentTo[pb])sentTo[pa].insert(x);
		set<int> allIncomers;
		makeParent(pa,pb,allIncomers);
		parent[pb] = pa;
		sz[pa] += sz[pb];
	
		for(auto e : allIncomers){
			handleEdge(e,pa);
		}
	}

	void handleEdge(int a,int b){
		//cout <<a << " " << b << endl;
		int pa = find(a);
		int pb = find(b);

		//cout << "We have to handle " << a+1 << " : " << b+1 << endl;
		if(pa == pb)return;
		// edge is a-> b
		if(incoming[pb].find(a) != incoming[pb].end())return;
		//cout << "We do have to solve it" << a+1 << " : " << b+1 << endl;
		if(incomingCliques[pa].find(pb) != incomingCliques[pa].end()){
			merge(a,b);
		}else{
			addEdge(a,b);
		}
	}
};	

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int n,m;
	cin >> n >> m;
	DSU dsu;
	FOR(i,m){
		int a,b;
		cin >> a >> b;
		a--;b--;
		dsu.handleEdge(a,b);
		cout << dsu.tot << endl;
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...