【PA2009】【BZOJ3498】Cakes

来源:互联网 发布:算法设计与分析的认识 编辑:程序博客网 时间:2024/05/29 03:14

Description

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

Input

The first line of the standard input contains two integers n and m (1<=N<=100000,1<=M<=250000) separated by a single space and denoting the number of confectioners at the convention and the number of pairs of them that like each other. The participants of the convention are numbered from 1 to N, The second line contains n integers pi (1<=Pi<=1000000) separated by single spaces and denoting the requirements of respective confectioners for flour (in decagrams). The following m lines contain data about pairs of contestants that like each other. Each of these lines contains two integers ai and bi (1<=ai,bi<=n Ai<>Bi) separated by a single space. They denote that confectioners ai and bi like each other. We assume that all pairs of participants of the convention apart from the ones listed in the input would not like to bake cakes together. Each pair of confectioners appears at most once in the input.

Output

The first and only line of the standard output should contain a single integer - the quantity of flour that will be used by all teams in total, in decagrams.

Sample Input

5 7

1 5 3 4 2

1 2

2 3

5 2

4 3

3 1

1 4

5 1

Sample Output

14

Explanation of the example. The following three-person teams: (1,2,3),(1,2,5) and (1,3,4)require 5, 5 and 4 decagrams of flour to bake the cakes. In total 5+5+4=14 decagrams of flour are required.

HINT

Source

考虑连边只从大的点向小的点连单向边,并记录每个点的出度.
对每个点开一个set
枚举一个环的起点x,再枚举出边,根据出边指向的点j的度数,
如果j的度数小于x的度数的3倍,直接再枚举j的出边看看是不是与x相连;
如果j的度数大于等于x的度数的3倍,就再枚举一遍x的出边,看指向的点是否与y相连.
这里用set判断相连其实可以改成hash,那样少个log…
3倍并不是玄学,只是一个限制时间的手段…
更加科学的限制手段可以像Claris把度数限制改成m,这样复杂度是十分科学而稳定的…我这个看起来有点玄学,有可能会被卡掉…

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<set>#define MAXN 100010#define MAXM 250010#define LL long long#define GET (ch>='0'&&ch<='9')using namespace std;int n,m,u,v,top,i,cnt;LL ans;int val[MAXN],id[MAXN],pos[MAXN];int d[MAXN],vis[MAXN];set<int> s[MAXN];struct edge {   int to;edge *next;  }e[MAXM<<1],*prev[MAXN];inline void insert(int u,int v) {   d[u]++;e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];   }void in(int &x){    char ch=getchar();x=0;    while (!GET)    ch=getchar();    while (GET) x=x*10+ch-'0',ch=getchar();}inline bool cmp(int a,int b)    {   return val[a]<val[b];   }int main(){    for (in(n),in(m),i=1;i<=n;i++)  in(val[i]),id[i]=i;    for (sort(id+1,id+n+1,cmp),i=n;i;i--)   pos[id[i]]=i;    for (i=m;i;i--)    {           in(u),in(v);        if (pos[u]<pos[v])  swap(u,v);        insert(u,v);    }    for (int j=1;j<=n;j++)    {        int x=id[j];++cnt;        for (edge *i=prev[x];i;i=i->next)   vis[i->to]=cnt;        for (edge *i=prev[x];i;i=i->next)        {            vis[i->to]=cnt;            if (d[i->to]<d[x]*3)                for (edge *I=prev[i->to];I;I=I->next)   ans+=(vis[I->to]==cnt)?val[x]:0;            else                    for (edge *I=prev[x];I;I=I->next)   ans+=s[i->to].count(I->to)?val[x]:0;            s[x].insert(i->to);        }    }    cout<<ans<<endl;}
1 0
原创粉丝点击