BZOJ 4264 小c找朋友 - hash
题目大意:
给定一张无向图,求满足以下条件的点对 (x,y) 数目:对任意点 z (z!=x,y),边 (x,z) 和 (y,z) 同时存在或同时不存在。
题目分析:
首先要分析的出如果xy满足要求,那么x和y的连边点集应该是相同的,这里又分为两种情况:
- xy之间有边,加上自己的hash值后求集合哈希值出现的次数
- xy之间没有边,直接hash求不包含自己的集合哈希值出现的次数
bzoj加上srand(time(0))就会RE,有毒
code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#include<ctime>
using namespace std;
typedef long long ll;
namespace IO{
inline int read(){
int i = 0, f = 1; char ch = getchar();
for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-') f = -1, ch = getchar();
for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
return i * f;
}
inline void wr(ll x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
}using namespace IO;
const int N = 1e6 + 5, M = 1e6 + 5;
int n, m;
typedef unsigned long long ull;
const int Mod = 233333;
ull val[N], sum[N];
ll ans, degree[N];
typedef pair<ull, ll> P;
typedef pair<int, int> EP;
vector<EP> edges;
vector<P> hashMap[Mod + 5];
inline void insert(ull x, ll c){
int key = x % Mod;
for(int i = 0; i < hashMap[key].size(); i++)
if(hashMap[key][i].first == x) {hashMap[key][i].second+=c;return;}
hashMap[key].push_back(P(x, c));
}
inline ll query(ull x){
int key = x % Mod;
for(int i = 0; i < hashMap[key].size(); i++)
if(hashMap[key][i].first == x) return hashMap[key][i].second;
return 0;
}
int main(){
n = read(), m = read();
for(int i = 1; i <= n; i++) val[i] = 1ull * rand() * rand() + rand() ;
for(int i = 1; i <= m; i++){
int x = read(), y = read(); edges.push_back(EP(x, y)); degree[x]++, degree[y]++;
sum[x] += val[y], sum[y] += val[x];
}
for(int i = 1; i <= n; i++) insert(sum[i],1);
for(int i = 1; i <= n; i++){
ll x = query(sum[i]); insert(sum[i], -x);
ans += x * (x - 1) / 2;
}
for(int i = 0; i < edges.size(); i++){
int x = edges[i].first, y = edges[i].second;
if(degree[x] == degree[y] && sum[x] + val[x] == sum[y] + val[y]) ans++;
}
wr(ans), putchar('\n');
return 0;
}