Codeforces Round #109 (Div. 2) E. Double Profiles hash

题目链接:

http://codeforces.com/problemset/problem/155/E

E. Double Profiles

time limit per test 3 seconds
memory limit per test 256 megabytes
#### 问题描述 > You have been offered a job in a company developing a large social network. Your first task is connected with searching profiles that most probably belong to the same user. > > The social network contains n registered profiles, numbered from 1 to n. Some pairs there are friends (the "friendship" relationship is mutual, that is, if i is friends with j, then j is also friends with i). Let's say that profiles i and j (i ≠ j) are doubles, if for any profile k (k ≠ i, k ≠ j) one of the two statements is true: either k is friends with i and j, or k isn't friends with either of them. Also, i and j can be friends or not be friends. > > Your task is to count the number of different unordered pairs (i, j), such that the profiles i and j are doubles. Note that the pairs are unordered, that is, pairs (a, b) and (b, a) are considered identical. #### 输入 > The first line contains two space-separated integers n and m (1 ≤ n ≤ 106, 0 ≤ m ≤ 106), — the number of profiles and the number of pairs of friends, correspondingly. > > Next m lines contains descriptions of pairs of friends in the format "v u", where v and u (1 ≤ v, u ≤ n, v ≠ u) are numbers of profiles that are friends with each other. It is guaranteed that each unordered pair of friends occurs no more than once and no profile is friends with itself. #### 输出 > Print the single integer — the number of unordered pairs of profiles that are doubles. > > Please do not use the %lld specificator to read or write 64-bit integers in С++. It is preferred to use the %I64d specificator. #### 样例 > **sample input** > 4 1 > 1 3 > > **sample output** > 2

题意

给你一个n个点m条边的无向图,让你求一些顶点对(无序)(u,v),满足对于任意的k(k!=u,v),k要么到两个点都有边,要么到两个点都没边,对于(u,v)本身可以存在边也可以不存在。

题解

这题如果你想到用hash,思路就会很直观了!
对于顶点u,我们把它的所有相邻的点(不包括它自己)都存起来,hash成一个x进制数ha[u](每个位对应一个节点,用加权的方式加起来)

接下来把顶点对分成两类:
1、顶点对之间没有边相邻:
如果两个顶点u,v它们的ha[u]=ha[v](即它们的相邻顶点集完全一样!),那么它们就是满足的顶点对。
2、顶点对之间没有边相邻:
如果ha[u]+u=ha[v]+v(u会出现在ha[v]里面,v会出现在ha[u]里面),同理,它们也满足条件。

对于有边的,一条一条统计。没边的吧ha数组排个序,扫一遍就可以了。

代码

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#define X first
#define Y second
#define mp make_pair
using namespace std;

const int maxn=1e6+10;
typedef unsigned __int64 LL;

const LL P=123;
int n,m;

LL pw[maxn];
LL ha[maxn];
void pre(){
	memset(ha,0,sizeof(ha));
	pw[0]=1;
	for(int i=1;i<maxn;i++) pw[i]=pw[i-1]*P;
}

int main(){
	pre();
	scanf("%d%d",&n,&m);
	vector<pair<int,int> > egs;
	for(int i=0;i<m;i++){
		int u,v; 
		scanf("%d%d",&u,&v);
		egs.push_back(mp(u,v));
		ha[u]+=pw[v];
		ha[v]+=pw[u];
	}
	LL ans=0;
	for(int i=0;i<m;i++){
		int u=egs[i].X,v=egs[i].Y;
		if(ha[u]+pw[u]==ha[v]+pw[v]) ans++;
	}
	sort(ha+1,ha+n+1);
	for(int i=1;i<n;i++){
		if(ha[i]==ha[i+1]){
			int ed=i;
			while(ed+1<=n&&ha[ed]==ha[ed+1]) ed++;
			LL len=ed-i+1;
			ans+=len*(len-1)/2;
			i=ed;
		}
	}
	printf("%I64d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/fenice/p/5694115.html