怎么说呢,这应该算是一种新知识吧,图上hash。
具体做法就是每个点都附上一个初值,然后把每个点所连的点的值“合”起来,然后就可以判断相连的点是否一样了(不包括自己),如果要让自己也在的话,再“合”上自己就好了。
关于怎么“合”,有多种方法,感觉一般采用二进制运算,因为不用考虑顺序呀。好像异或的正确率比较高呀。
#include<bits/stdc++.h>
#define N 1000000
using namespace std;
int n,m,x,y,cnt;
unsigned long long val[N+5];
unsigned long long H[N+5],a[N+5];
long long ans;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
int x=0,b=1;
char c=nc();
for(;!(c<='9'&&c>='0');c=nc())if(c=='-')b=-1;
for(;c<='9'&&c>='0';c=nc())x=x*10+c-'0';
return x*b;
}
int main()
{
freopen("in.txt","r",stdin);
n=read(),m=read();
for(int i=1;i<=n;i++)val[i]=val[i-1]*233+7;
for(int i=1;i<=m;i++)
{
x=read(),y=read();
H[x]^=val[y],H[y]^=val[x];
}
memcpy(a,H,sizeof(H));
sort(a+1,a+n+1);cnt=1;
for(int i=2;i<=n;i++)if(a[i]==a[i-1])cnt++;else ans+=(long long)cnt*(cnt-1)/2,cnt=1;
ans+=(long long)cnt*(cnt-1)/2;
for(int i=1;i<=n;i++)H[i]^=val[i];
memcpy(a,H,sizeof(H));
sort(a+1,a+n+1);cnt=1;
for(int i=2;i<=n;i++)if(a[i]==a[i-1])cnt++;else ans+=(long long)cnt*(cnt-1)/2,cnt=1;
ans+=(long long)cnt*(cnt-1)/2;
cout<<ans;
return 0;
}