码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3498: PA2009 Cakes

时间:2017-08-03 16:51:14      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:rip   long   bool   char   时间复杂度   列表   平衡   散列   return   

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\n",ans/3);
    return 0;
}

 

 

bzoj3498: PA2009 Cakes

标签:rip   long   bool   char   时间复杂度   列表   平衡   散列   return   

原文地址:http://www.cnblogs.com/ccz181078/p/7280325.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!