zoukankan      html  css  js  c++  java
  • bzoj3498: PA2009 Cakes

    Description

    N个点m条边,每个点有一个点权a。
    对于任意一个三元环(j,j,k)(i<j<k),它的贡献
    为max(ai,aj,ak) 
    求所有三元环的贡献和。
    N<100000,,m<250000。

    对度数大的点w,枚举w相邻的每个点u1,u2,u3...,遍历u[a]相邻的点的统计w,u[a],u[b](b<a)构成三元环的情况

    对度数小的点w,枚举w相邻的每个点,在另外存边的散列表中 判断它们两两之间是否有边

    每个三元环恰好统计三次,两种策略时间复杂度在判断标准为$sqrt{m}$时达到平衡

    #include<cstdio>
    #include<vector>
    const int RN=1e5;
    char buf[RN+7],*ptr=buf+RN;
    int G(){
        if(ptr==buf+RN)fread(ptr=buf,1,RN,stdin);
        return *ptr++;
    }
    int _(){
        int x=0;
        if(ptr<buf+RN-50){
            while(*ptr<48)++ptr;
            while(*ptr>47)x=x*10+*ptr++-48;
        }else{
            int c=G();
            while(c<48)c=G();
            while(c>47)x=x*10+c-48,c=G();
        }
        return x;
    }
    const int P=1844677,N=1e5+7,D=333;
    int n,m,a[N],ed[N],e[N*3][2],deg[N],*lr[N][2],mem[N*5],*mp=mem;
    int max(int a,int b){return a>b?a:b;}
    long long ans=0;
    int h[P][2];
    void ins(int a,int b){
        int w=(a*1399+b*2939)%P;
        while(h[w][0]){
            if(h[w][0]==a&&h[w][1]==b)return;
            w=(w+21331)%P;
        }
        h[w][0]=a,h[w][1]=b;
    }
    bool find(int a,int b){
        int w=(a*1399+b*2939)%P;
        while(h[w][0]){
            if(h[w][0]==a&&h[w][1]==b)return 1;
            w=(w+21331)%P;
        }
        return 0;
    }
    int main(){
        n=_(),m=_();
        for(int i=1;i<=n;++i)a[i]=_();
        for(int i=1;i<=m;++i){
            ++deg[e[i][0]=_()];
            ++deg[e[i][1]=_()];
        }
        for(int i=1;i<=n;++i)lr[i][0]=lr[i][1]=mp,mp+=deg[i];
        for(int i=1;i<=m;++i){
            int a=e[i][0],b=e[i][1];
            *lr[a][1]++=b;
            *lr[b][1]++=a;
            ins(a,b);
            ins(b,a);
        }
        for(int i=1;i<=n;++i)if(deg[i]>D){
            for(int*j=lr[i][0];j!=lr[i][1];++j){
                int w=*j,mx=max(a[i],a[w]);
                ed[w]=i;
                for(int*k=lr[w][0];k!=lr[w][1];++k)if(ed[*k]==i)ans+=max(mx,a[*k]);
            }
        }else{
            for(int*j=lr[i][0];j!=lr[i][1];++j){
                int w=*j,mx=max(a[i],a[w]);
                for(int*k=lr[i][0];k!=j;++k)if(find(w,*k))ans+=max(mx,a[*k]);
            }
        }
        printf("%lld
    ",ans/3);
        return 0;
    }
     
  • 相关阅读:
    计算机操作系统 存储器管理
    数据结构 平衡二叉树avl c++
    数据结构 线索二叉树 c++
    数据结构 赫夫曼树及其应用 c++
    c++ cstring 常用函数
    数据结构 哈希表 c++
    数据结构 静态链表
    ajax返回填充的数据不显示
    使用JSON.parse()转化成json对象需要注意的地方
    参数错误导致bug
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7280325.html
Copyright © 2011-2022 走看看