BZOJ 3498: PA2009 Cakes【三元环】

3498: PA2009 Cakes

【题目描述】
传送门

【题解】

求解三元环,枚举每条边,然后枚举点,判断是否组成三元环(可以用hash来判断),复杂度O(m32)

代码如下

#include<cmath>
#include<cstdio>
#include<vector>
#include<cctype>
#include<algorithm>
using namespace std;
const int MOD=(1<<23)-1;
int n,m,Size,W[100005],C[100005];
long long Ans;
struct xcw{
    int x,y;
    bool operator <(const xcw b)const{return x<b.x||x==b.x&&y<b.y;}
}a[250005];
struct Edge{
    int tot,lnk[100005],son[250005<<1],nxt[250005<<1],F[250005<<1],hlnk[MOD+5];
    void Add(int x,int y){son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;}
    int hsh(int x,int y){return (x<<8|y)&MOD;}
    void Add_hsh(int x,int y){
        int j=hsh(x,y);
        son[++tot]=y;F[tot]=x;
        nxt[tot]=hlnk[j];hlnk[j]=tot;
    }
    bool Fnd(int x,int y){
        int i=hsh(x,y);
        for(int j=hlnk[i];j;j=nxt[j]) if(x==F[j]&&y==son[j]) return 1;
        return 0;
    }
}E;
vector <int> Son[100005];
int read(){
    int ret=0;char ch=getchar();bool f=1;
    for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
    for(; isdigit(ch);ch=getchar()) ret=(ret<<3)+(ret<<1)+ch-48;
    return f?ret:-ret;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("3498.in","r",stdin);
    freopen("3498.out","w",stdout);
    #endif
    n=read(),m=read();Size=sqrt(m);
    for(int i=1;i<=n;i++) W[i]=read();
    for(int i=1;i<=m;i++){
        a[i]=(xcw){read(),read()};
        if(a[i].x<a[i].y) swap(a[i].x,a[i].y);
        C[a[i].x]++;
    }
    sort(a+1,a+1+m);
    for(int i=1;i<=m;i++) E.Add_hsh(a[i].x,a[i].y),E.Add(a[i].x,a[i].y),Son[a[i].x].push_back(a[i].y);
    for(int i=3;i<=n;i++)
    for(int j=E.lnk[i];j;j=E.nxt[j]){
        int x=E.son[j];
        if(C[x]>Size){
            for(int k=E.nxt[j];k;k=E.nxt[k]){
                int y=E.son[k];
                if(y>=x) continue;
                if(E.Fnd(x,y)) Ans+=max(W[i],max(W[x],W[y]));
            }
        }else{
            for(int k=E.lnk[x];k;k=E.nxt[k]){
                int y=E.son[k];
                if(E.Fnd(i,y)) Ans+=max(W[i],max(W[x],W[y]));
            }
        }
    }
    printf("%lld\n",Ans);
    return 0;
}
posted @ 2018-07-03 14:58  XSamsara  阅读(99)  评论(0编辑  收藏  举报