Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- typedef long double ld;
- typedef unsigned long long ull;
- typedef pair<ll,ll> ii;
- typedef vector<ll> vi;
- typedef vector< ii > vii;
- #define INF 0x3F3F3F3F
- #define LINF 0x3F3F3F3F3F3F3F3FLL
- #define pb push_back
- #define mp make_pair
- #define pq priority_queue
- #define LSONE(s) ((s)&(-s)) //LASTBIT
- #define DEG_to_RAD(X) (X * PI / 180)
- #define F first
- #define S second
- #define PI 2*acos(0)
- #ifdef ONLINE_JUDGE
- #define debug(args...)
- #else
- #define debug(args...) fprintf(stderr,args)
- #endif
- //////////////////////
- int dx[] = {1,-1,0,0};
- int dy[] = {0,0,-1,1};
- //////////////////////
- /*
- Author: Junior Andrade
- */
- void arquivo(){
- freopen("","r",stdin);
- freopen("","w",stdout);
- }
- const int N = 200000;
- vi g[N], tree[N], rg[N], bucket[N];
- int sdom[N], par[N], dom[N], dsu[N], label[N];
- int arr[N], rev[N], T;
- int n,m;
- int Find(int u,int x=0)
- {
- if(u==dsu[u])return x?-1:u;
- int v = Find(dsu[u],x+1);
- if(v<0)return u;
- if(sdom[label[dsu[u]]] < sdom[label[u]])
- label[u] = label[dsu[u]];
- dsu[u] = v;
- return x?v:label[u];
- }
- void Union(int u,int v) //Add an edge u-->v
- {
- dsu[v]=u; //yup,its correct :)
- }
- void dfs0( int x ){
- T++; arr[x] = T; rev[T] = x;
- label[T] = T; sdom[T] = T; dsu[T] = T;
- for(int i=0;i<g[x].size();++i){
- int y = g[x][i];
- if( !arr[y] ){
- dfs0(y);
- par[arr[y]] = arr[x];
- }
- rg[arr[y]].pb(arr[x]);
- }
- }
- void processTree(){
- T = 0;
- dfs0(1);
- n = T;
- for(int i=n;i>=1;i--)
- {
- for(int j=0;j<rg[i].size();j++) sdom[i] = min(sdom[i],sdom[Find(rg[i][j])]);
- if(i>1) bucket[sdom[i]].pb(i);
- for(int j=0;j<bucket[i].size();j++)
- {
- int w = bucket[i][j];
- int v = Find(w);
- if(sdom[v]==sdom[w]) dom[w]=sdom[w];
- else dom[w] = v;
- }
- if(i>1)Union(par[i],i);
- }
- for(int i=2;i<=n;i++)
- {
- if(dom[i]!=sdom[i]) dom[i]=dom[dom[i]];
- tree[rev[i]].pb(rev[dom[i]]);
- tree[rev[dom[i]]].pb(rev[i]);
- }
- }
- ll subSize[N];
- ll ans;
- void dfs( int x, int ult ){
- subSize[x] = 1;
- for(int i=0;i<tree[x].size();++i){
- int y = tree[x][i];
- if( y == ult ) continue;
- dfs(y,x);
- subSize[x]+=subSize[y];
- if( x == 1 ) ans -= (subSize[y]*1LL*(subSize[y]-1LL))/2LL;
- }
- }
- int main(){
- //ios::sync_with_stdio(0);
- scanf("%d %d",&n,&m);
- for(int i=0;i<m;++i){
- int x,y; scanf("%d %d",&x,&y);
- g[x].pb(y);
- }
- processTree();
- ans = (n*1LL*(n-1LL))/2LL;
- dfs(1,1);
- printf("%lld\n",ans);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement