23 Sep 2016

CodeChef May15 Task10 GRAPHCNT dominator tree

题目大意:

给定一个$n$个点$m$条边无向图$G$, 问有多少点对$(u,v)$满足有$(1 \to u)$的路径以及$( 1 \to v)$的路径,并且两条路径除了$1$没有其他交点


题解:

你妹就一dominator tree裸题

正难则反。观察到直接数这些点对不方便,那么可以换个思路,数那些除了$1$还有其他交点的路径。

首先肯定是以$1$为根搞出一个Flow Graph

如果两个点的路径除了$1$还有其他交点$x$,$x$是有向图的一个割点

所以我们套用dominator tree求一下有向图割点就好了。


Code

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
#define pb push_back
#define bug(x) cout<<#x<<"="<<x<<" "
#define debug(x) cout<<#x<<"="<<x<<endl
typedef long long ll;
typedef vector<int> vec;
const int M=1e5+5;
vec pre[M],G[M],dom[M];
inline void rd(int &a){
	a=0;char c;
	while(c=getchar(),!isdigit(c));
	do a=a*10+(c^48);
		while(c=getchar(),isdigit(c));
}
int dfn[M],tid[M],anc[M],dfs_clock;
int idom[M],semi[M],best[M],f[M];
inline void predfs(int v){
	dfn[v]=++dfs_clock,tid[dfs_clock]=v;
	semi[dfs_clock]=anc[dfs_clock]=best[dfs_clock]=dfs_clock;
	for(int i=0;i<G[v].size();++i){
		int to=G[v][i];
		if(!dfn[to])predfs(to),f[dfn[to]]=dfn[v];
	}
}
int sz[M];
inline void dfs(int v){
	sz[v]=1;
	for(int i=0;i<dom[v].size();++i){
		int to=dom[v][i];
		dfs(to);
		sz[v]+=sz[to];
	}
}
inline int get(int x){
	if(anc[x]==x)return x;
	int y=get(anc[x]);
	if(semi[best[x]]>semi[best[anc[x]]])best[x]=best[anc[x]];
		//maintain
	anc[x]=y;//path compression
	return y;
}
inline void Min(int &a,int b){
	if(a>b)a=b;
}
int main(){
	int n,m;cin>>n>>m;
	for(int i=1,a,b;i<=m;++i){
		rd(a),rd(b);
		G[a].pb(b),pre[b].pb(a);
	}
	predfs(1);
	for(int y=dfs_clock;y>1;--y){
		int x=f[y],w=tid[y];
		for(int i=0;i<pre[w].size();++i){
			int z=dfn[pre[w][i]];
			if(!z)continue;
			get(z);
			Min(semi[y],semi[best[z]]);
		}
		dom[semi[y]].pb(y);
		anc[y]=x;
		for(int i=0,z;i<dom[x].size();++i){
			z=dom[x][i];
			get(z);
			if(semi[best[z]]<x)idom[z]=best[z];
			else idom[z]=x;
		}
		dom[x].clear();
	}
	for(int i=2;i<=dfs_clock;++i){
		if(idom[i]!=semi[i])idom[i]=idom[idom[i]];
		dom[idom[i]].pb(i);
	}
	ll res=(ll)(dfs_clock-1)*dfs_clock>>1ll;
	for(int i=0;i<dom[1].size();++i){
		int to=dom[1][i];
		dfs(to);
		res-=(ll)sz[to]*(sz[to]-1)>>1ll;
	}
	cout<<res<<endl;
	return 0;
}

Tags:
Stats:
comments


Share:


Comments: