Codeforces 154 C. Double Profiles

問題

n個の頂点、m本の辺からなる無向グラフが与えられる。
このグラフにおいて、頂点のペア(i, j)がdoubleであるとは、
任意のノードkについて、i-kに辺があるときはj-kに辺があり、i-kに辺がないときはj-kに辺がないようなことを言う。
(i-jには辺があってもなくてもいい)


このとき、doubleなペアの総数を求めよ。

制約条件

n, m≦10^6

方針

直接つながっていないi,jについては、
iの隣接ノードとjの隣接ノードが等しければdouble.
これは、頂点ごとに隣接ノードの集合をハッシュで持っておけばO(1)で判定できる。

(ペアを全て試すとTLEなので、等しいハッシュ値を持つ頂点の個数からペアの個数を求める)


直接つながっているノードi,jについては
iの隣接ノードにi自身を加え、jの隣接ノードにj自身を加えてハッシュが等しいかを見る。

ソースコード

int n, m;
vi e[1000001];
ll h[1000001], p[1000001];

void run()
{
	scanf("%d%d",&n,&m);
	p[0]=1;
	rep(i,n)p[i+1]=p[i]*1007;
	rep(i,m){
		int a, b; scanf("%d%d",&a,&b);
		e[--a].pb(--b);
		//e[b].pb(a);
		h[a]+=p[b];
		h[b]+=p[a];
	}
	map<ll,int> cnt;
	rep(i,n)cnt[h[i]]++;
	ll ans=0;
	fr(i,cnt)ans+=(ll)i->second*(i->second-1)/2;
	rep(i,n)rep(j,e[i].size())if(h[i]+p[i]==h[e[i][j]]+p[e[i][j]])ans++;
	cout<<ans<<endl;
}