4264: 小C找朋友 hash

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/83868590

题解:

这道题目一眼就hash啊……但是我还是没做出来,因为我的hash方法太过naive了,直接用一个二进制表示每个人的朋友集合……正解的hash方法其实也接触过,但是我没用过太多,记录一下:给每个人随机一个很大的权值,一个人朋友集合的表示方法就是把它的朋友的权值异或起来。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=1000010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
map<int,bool>mp[Maxn];
int n,m;
LL v[Maxn],a[Maxn];
struct Edge
{
    int x,y;
    Edge(int _x=0,int _y=0){x=_x,y=_y;}
}e[Maxn];int len=0;
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)v[i]=v[i-1]*233+17;
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        if(x>y)swap(x,y);
        if(!mp[x][y])
        {
            mp[x][y]=true;
            a[x]^=v[y];a[y]^=v[x];
            e[++len]=Edge(x,y);
        }
    }
    LL ans=0;
    for(int i=1;i<=len;i++)
    {
        int x=e[i].x,y=e[i].y;
        if((a[x]^v[y])==(a[y]^v[x]))ans++;
    }
    sort(a+1,a+1+n);
    LL last=a[1],t=1;
    for(int i=2;i<=n;i++)
    if(a[i]==last)t++;
    else
    {
        ans+=t*(t-1)/2LL;
        last=a[i];t=1;
    }
    ans+=t*(t-1)/2LL;
    printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/83868590