4264:小C找朋友(hash)
阿新 • • 發佈:2018-11-07
小C找朋友
題目描述
幼兒園裡有 個小 ,兩個小 之間可能是朋友也可能不是。所有小 之間的朋友關係構成了一個無向圖,這個無向圖中有 條邊。
園長ATM發現對於兩個(不同的)小
和
,如果其他的所有小
要麼同時是
,
的朋友,要麼同時不是
,
朋友的話,這兩個小
就很有可能一起去吃飯,成為一對好基友。出於一些未知的原因,ATM需要你幫他求出可能成為好基友的小C的對數。
輸入
第一行一個數
,
,如題目描述。
接下來
行,每行2個數表示一條無向邊。
輸出
輸出可能成為好基友的小 的對數。
輸入樣例
3 3
1 2
2 3
1 3
輸出樣例
3
提示
解:
一道很簡單的題目。如何快速判斷連邊相等?自然而然想到了hash。把一個點連向的邊全部異或起來存在這個點裡,然後朋友一樣的點的值相同。但是他們兩個如果是朋友的話這個值就不一樣了。於是我們再異或一下自己再做一遍。
但是這樣容易衝突。我們給每個點rand一個
權值,再那麼做就好啦。(開個map存一下)
code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<map>
using namespace std;
unsigned long long r[1000005];
unsigned long long p[1000005];
map <unsigned long long,int> d;
int n,m,x,y;
long long ans;
int main()
{
srand(19260817);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) r[i]=1ll*rand()*rand()*rand()*rand()*rand();
for(int i=1;i<=m;i++)
scanf("%d%d",&x,&y),p[x]^=r[y],p[y]^=r[x];
for(int i=1;i<=n;i++){
ans+=d[p[i]];
d[p[i]]++;
}
d.clear();
for(int i=1;i<=n;i++) p[i]^=r[i];
for(int i=1;i<=n;i++){
ans+=d[p[i]];
d[p[i]]++;
}
printf("%lld",ans);
}