BZOJ 4264 小C找朋友 哈希+脑子

蔚落 2021-11-17 15:28 295阅读 0赞

好吧我觉得是脑子,别人觉得是套路$qwq$


这道题相当于是求除了$u,v$两点互相连接,所连的点相同的点对$(u,v)$

我们首先每个点一个随机权值,对于$u$点记为$w[u]$,然后记与$u$点相连的点的异或和为$hsh[u]$

分类:

  1. 若$u,v$相连,则$u,v$是朋友满足$(hsh[u]^w[v])==(hsh[v]^w[u])$;
  2. 若$u,v$不相连,则$u,v$是朋友满足$hsh[u]==hsh[v]$;

对于第一种情况,直接枚举每条边上的两点就行了;对于第二种情况,先把$hsh$数组$sort$一遍,然后对于$hsh$相同的点来说,设共有$cnt$个点的$hsh[u]==c$,$c$是某定值,则答案个数是$C_{cnt}^2$。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<cctype>
  7. #include<cstdlib>
  8. #include<vector>
  9. #include<queue>
  10. #include<map>
  11. #include<set>
  12. #define fr first
  13. #define sc second
  14. #define ull unsigned long long
  15. #define ll long long
  16. #define R register int
  17. using namespace std;
  18. namespace Fread {
  19. static char B[1<<15],*S=B,*D=B;
  20. #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
  21. inline int g() {
  22. R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
  23. do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
  24. }
  25. }using Fread::g;
  26. const int N=1000010;
  27. pair<int,int> e[N];
  28. int n,m; ll ans;
  29. ull vl[N],hsh[N];
  30. signed main() {
  31. #ifdef JACK
  32. freopen("NOIPAK++.in","r",stdin);
  33. #endif
  34. n=g(),m=g(); srand(100023323);
  35. for(R i=1;i<=n;++i) vl[i]=(ull)rand()*rand()*rand()*rand();
  36. for(R i=1,u,v;i<=m;++i) u=e[i].fr=g(),v=e[i].sc=g(),hsh[u]^=vl[v],hsh[v]^=vl[u];
  37. for(R i=1;i<=m;++i) ans+=(int)((hsh[e[i].fr]^vl[e[i].sc])==(hsh[e[i].sc]^vl[e[i].fr]));
  38. sort(hsh+1,hsh+n+1); R cnt=0; for(R i=1;i<=n;++i) {
  39. ++cnt; if(i==n||hsh[i]!=hsh[i+1]) ans+=(ll)cnt*(cnt-1)/2,cnt=0;
  40. } printf("%lld",ans);
  41. }

2019.06.10

转载于:https://www.cnblogs.com/Jackpei/p/11000339.html

发表评论

表情:
评论列表 (有 0 条评论,295人围观)

还没有评论,来说两句吧...

相关阅读

    相关 关于关于关于

    今天老师讲了哈希,草草地整理一下: 哈希表,也称散列表,是一种高效的数据结构。它的最大优点就是把数据存储和查找所消耗的时间大大降低,几乎可以看成是 O(1)的,而代价是消耗比