제출 #1262778

#제출 시각아이디문제언어결과실행 시간메모리
1262778bot1132조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2)C++20
100 / 100
968 ms64908 KiB
#include <bits/stdc++.h> using namespace std; using ll=long long; #define pb push_back #define mp make_pair #define F first #define S second #define si(x) int(x.size()) template<class t>using vc=vector<t>; using pl=pair<ll,ll>; ll n,m,par[100005],sz[100005],ans; set<ll>in[100005],ins[100005]; set<pl>out[100005]; queue<pl>mg; ll find(ll x){ if(x==par[x])return x; return par[x]=find(par[x]); } void unite(ll x,ll y){ x=find(x); y=find(y); par[y]=x; sz[x]+=sz[y]; } void erase_edge(ll a,ll b){ b=find(b); out[find(a)].erase(mp(a,b)); in[b].erase(a); } bool add_edge(ll a,ll b){ b=find(b); ll p=find(a); if(p==b||out[p].find(mp(a,b))!=out[p].end())return false; in[b].insert(a); out[p].insert(mp(a,b)); ins[b].insert(p); if(ins[p].find(b)!=ins[p].end())mg.push(mp(p,b)); return true; } ll cnt_edge(ll x){ return sz[x]*(sz[x]-1LL)+ll(si(in[x]))*sz[x]; } void mrg(ll x,ll y){ if(si(in[x])+si(out[x])<si(in[y])+si(out[y]))swap(x,y); ans-=cnt_edge(x); ans-=cnt_edge(y); vc<pl>erase; vc<pl>add; for(auto &i:in[y]){ erase.pb(mp(i,y)); if(find(i)!=x)add.pb(mp(i,y)); } for(auto &i:out[y]){ erase.pb(mp(i.F,i.S)); if(i.S!=x)add.pb(mp(i.F,i.S)); } for(auto &i:erase)erase_edge(i.F,i.S); unite(x,y); for(auto &i:add)add_edge(i.F,i.S); ans+=cnt_edge(x); } int main(void){ cin.tie(0); ios::sync_with_stdio(0); cin>>n>>m; for(int i=0;i<n;i++){ par[i]=i; sz[i]=1; } while(m--){ ll a,b; cin>>a>>b; a--,b--; if(add_edge(a,b)){ ans+=sz[find(b)]; } while(!mg.empty()){ ll x=find(mg.front().F),y=find(mg.front().S); mg.pop(); if(x!=y)mrg(x,y); } cout<<ans<<endl; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...