bzoj3498: PA2009 Cakes

题目描述:

N个点m条边,每个点有一个点权a。
对于任意一个三元环 $(i,j,k) (i为 $max(a_i,a_j,a_k)$  
求所有三元环的贡献和。
$N\le 100000,m\le 250000$。

算法标签:三元环

思路:

裸的三元环模板题拉。

主要思路是按照度数排序对于双向边之连接度数大指向度数小的单向边,这样每个三元环只算一次。

效率是 $O(nlogm+mlogm)$ 。

以下代码:

#include
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1e5+5,M=25e4+5;
LL ans;
bool vis[N];
int n,m,a[N],in[N],head[N],ne[M],to[M],cnt;
struct node{
    int l,r;
}t[M]; 
il int read(){
    int x,f=1;char ch;
    _(!)ch=='-'?f=-1:f;x=ch^48;
    _()x=(x<<1)+(x<<3)+(ch^48);
    return f*x;
}
il void insert(int x,int y){
    ne[++cnt]=head[x];
    head[x]=cnt;to[cnt]=y;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        in[x]++;in[y]++;
        t[i]=(node){x,y};
    }
    for(int i=1;i<=m;i++){
        int x=t[i].l,y=t[i].r;
        if(in[x]<in[y]||(in[x]==in[y]&&x>y))swap(x,y);
        insert(x,y);
    }
    for(int x=1;x<=n;x++){
        for(int i=head[x];i;i=ne[i])vis[to[i]]=1;
        for(int i=head[x];i;i=ne[i]){
            int v=to[i];
            for(int j=head[v];j;j=ne[j]){
                if(vis[to[j]]){
                    ans+=max(a[x],max(a[v],a[to[j]]));
                }
            }
        }
        for(int i=head[x];i;i=ne[i])vis[to[i]]=0;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Jessie-/p/10427835.html

你可能感兴趣的:(bzoj3498: PA2009 Cakes)