Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********* Dominator Tree for Directed General Graph ***********/
- /*
- Sample Problem: Given an undirected graph with N nodes and M edges, calculate the number
- of unordered pairs(X, Y) such there exists two paths, one from node 1 to node X, and
- another from node 1 to node Y, such that they don't share any node except node 1.
- */
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long int LL;
- const int N = int(1e5)+10;
- const int M = int(5e5)+10;
- vector<int> g[N];
- vector<int> tree[N],rg[N],bucket[N];
- int sdom[N],par[N],dom[N],dsu[N],label[N];
- int arr[N],rev[N],T;
- LL ans;
- 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 u)
- {
- T++;arr[u]=T;rev[T]=u;
- label[T]=T;sdom[T]=T;dsu[T]=T;
- for(int i=0;i<g[u].size();i++)
- {
- int w = g[u][i];
- if(!arr[w])dfs0(w),par[arr[w]]=arr[u];
- rg[arr[w]].push_back(arr[u]);
- }
- }
- int dfs(int u,int p)
- {
- int ret=1;
- for(int i=0;i<tree[u].size();i++)
- {
- int w = tree[u][i];
- if(w==p)continue;
- int x = dfs(w,u);
- if(u==1)ans -= (x*1ll*(x-1ll))/2ll;
- ret+=x;
- }
- return ret;
- }
- int main()
- {
- int n,m;
- scanf("%d %d", &n, &m);
- for(int i=0;i<m;i++)
- {
- int u,v;
- scanf("%d %d", &u, &v);
- g[u].push_back(v);
- }
- //Build Dominator tree
- 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]].push_back(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]].push_back(rev[dom[i]]);
- tree[rev[dom[i]]].push_back(rev[i]);
- }
- //done :)
- ans = (n*1ll*(n-1ll))/2ll;
- dfs(1,1);
- printf("%lld\n", ans);
- return 0;
- }
- /*
- 6 6
- 1 2
- 1 3
- 1 4
- 2 5
- 2 6
- 3 6
- */
- /*
- 14
- */
Advertisement
Add Comment
Please, Sign In to add comment