赞
踩
它实际上是想始终保证复杂度为m×根号m,也就是保证枚举的边数尽可能小于根号m。所以判断一下,小于根号m直接可以进行下一个点的枚举就像dfs深搜一样,如果大了,我们不继续,而是从最初点上枚举别的就像bfs广搜一样
代码:
- /*
- * 无向图求三元环
- */
-
- #include<cstdio>
- #include<vector>
- #include<unordered_set>
- #include<cmath>
-
- using namespace std;
-
- typedef long long ll;
-
- const int maxn=1e5+10;
-
- vector<int> g[maxn];
- unordered_set<ll> st;
-
- int vis[maxn],link[maxn],out[maxn];
-
- int main(){
- ll ans,sum;
- int n,m,x,y,z,B;
- while(scanf("%d%d",&n,&m)!=EOF){
- B=sqrt(m);
- st.clear();
- for(int i=1;i<=n;i++){
- g[i].clear();
- vis[i]=link[i]=out[i]=0;
- }
- for(int i=1;i<=m;i++){
- scanf("%d%d",&x,&y);
- g[x].push_back(y);
- out[x]++;
- g[y].push_back(x);
- out[y]++;
- st.insert((ll)n*x+y); //对于大于根号下m的边不好这样进行判断时候有边相连,速度快而且更加家简便
- st.insert((ll)n*y+x);
- }
- ans=0;
- for(int i=1;i<=n;i++){
- x=i;
- vis[x]=1;
- for(int j=0;j<g[x].size();j++){
- link[g[x][j]]=x;
- }
- for(int j=0;j<g[x].size();j++){
- sum=0;
- y=g[x][j]; //枚举第二个点,第一条边
- if(vis[y]) continue;
- if(out[y]<=B){
- for(int k=0;k<g[y].size();k++){
- z=g[y][k];
- if(link[z]==x) sum++;
- }
- }else{
- for(int k=0;k<g[x].size();k++){
- z=g[x][k];
- if(st.find((ll)z*n+y)!=st.end()) sum++;
- }
- }
- ans+=sum;
- }
- }
- printf("%lld\n",ans/3);
- }
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。