解题报告:HDU_6184 Counting Stars (三元环计数)

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

题目链接


题意:

给定一张无向图,求以下图形的方案数,点集或边集不同认为是不同方案

(点数和<=3e5,边数和<=6e5,数据组数<=300)


思路:

考虑中间的边,它组成的三元环中任选两个都能组成不同的满足要求的图案

因此跑一遍三元环统计出每条边能组成的三元环个数

偷懒用unordered_map可以卡时限过,最好用hash


代码:

#include<bits/stdc++.h>

#define LL long long
#define pii pair<LL,int>
#define fi first
#define se second
const int N = 3e5+10;
const int mod = 1e5+3;
using namespace std;

int num[N];
vector<int>G[N],pos;
vector< pii >M[mod];
inline LL code(LL a,LL b){if(a>b)swap(a,b);
   return (a<<18)|b;
}
inline bool check(int a,int b){
   LL k = code(a,b);int p = k % mod;
   for(int i=0;i<M[p].size();i++)if(M[p][i].fi==k)return true;
   return false;
}

inline void add(int a,int b){
   LL k = code(a,b);int p = k % mod;
   M[p].emplace_back(pii(k,0));
}
inline void add(int a,int b,bool f){
   LL k = code(a,b);int p = k % mod;
   for(int i=0;i<M[p].size();i++)if(M[p][i].fi==k){
      ++M[p][i].se;return ;
   }
}

inline 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*10+ch-'0'; ch=getchar();}
    return x*f;
}

int main()
{
   int n,m;
   while(scanf("%d%d",&n,&m)==2){pos.clear();
      for(int i=1;i<=n;i++)G[i].clear();
      for(int i=0;i<mod;i++)M[i].clear();
      for(int i=0,s,e;i<m;++i){
         s = read(); e = read();
         G[s].emplace_back(e);add(s,e);
         G[e].emplace_back(s);
      }LL ans = 0 ; m = sqrt(m+0.5);
      for(int i=1,a,b;i<=n;i++)
         if(G[i].size()>m)pos.emplace_back(i);
         else for(int j=0;j<G[i].size();j++)if(G[a=G[i][j]].size()>m||a>i)
              for(int k=j+1;k<G[i].size();k++)if((G[b=G[i][k]].size()>m||b>i)&&check(a,b))
                 add(a,b,1),add(a,i,1),add(b,i,1);
      for(int i=0,a,b,c;i<pos.size();i++)for(int j=i+1;j<pos.size();j++)if(check(a=pos[i],b=pos[j]))
      for(int k=j+1;k<pos.size();k++)if(check(a,c=pos[k])&&check(b,c))
         add(a,b,1),add(b,c,1),add(a,c,1);
      for(int i=0;i<mod;i++)for(int j=0;j<M[i].size();j++)ans += 1LL * M[i][j].se * (M[i][j].se-1) / 2;
      printf("%lld\n",ans);
   }return 0;
}


阅读更多

没有更多推荐了,返回首页