BZOJ 3498: PA2009 Cakes

Description

\(n\)个点\(m\)条边,求所有三元环,一个三元环的贡献为三个点中权值最大的点.\(n\leqslant 1\times 10^5,n\leqslant 2.5\times 10^5\)

Solution

分类讨论.

只从权值大的点连向权值小的点,因为可能权值相同,顺序需要确定下来.

枚举所有边.

如果一个点的度数小于等于\(\sqrt m\)那么枚举所有的点,看看他和另一个点有没有连边,直接用map存一下...

如果度数大于\(\sqrt m\)那么枚举另一个点的所有相邻的点,如果另一个点度数大于\(\sqrt m\),那么这种情况最多有\(\sqrt m\)个...

总复杂度\(O(m\sqrt m)\)

Code

/**************************************************************
    Problem: 3498
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:5376 ms
    Memory:18248 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
#define uor(i,j,k) for(int i=j;i<=(int)k;i++)
#define uep(i,j,k) for(int i=j;i<(int)k;i++) 
 
typedef long long ll;
const int N = 100050;
inline int in(int x=0,char s=getchar()) { while(s>'9'||s<'0')s=getchar();
    while(s>='0'&&s<='9')x=x*10+s-'0',s=getchar();return x; }
 
int n,m,B;ll ans=0;
int a[N],de[N],du[N],id[N],rk[N];
vector<int> g[N];
map<int,bool> mp[N];
 
int cmp(const int &x,const int &y) { return a[x]<a[y]; }
void AddEdge(int fr,int to) { g[fr].push_back(to),du[fr]++; }
 
int main() {
    n=in(),m=in(),B=sqrt(m)+1;
    uor(i,1,n) a[i]=in(),id[i]=i;
    sort(id+1,id+n+1,cmp);
    uor(i,1,n) rk[id[i]]=i;
    uor(i,1,m) {
        int u=in(),v=in();
        if(rk[u]<rk[v]) swap(u,v);
        AddEdge(u,v);
    }
    uor(i,1,n) {
        int u=id[i];
        uep(j,0,g[u].size()) de[g[u][j]]=i;
        uep(j,0,g[u].size()) {
            int v=g[u][j];
            if(du[v]>B) uep(k,0,g[u].size()) ans+=mp[v][g[u][k]]?a[u]:0;
            else uep(k,0,g[v].size()) ans+=de[g[v][k]]==i?a[u]:0;
            mp[u][v]=1;
        }
    }return printf("%lld\n",ans),0;
}

  

posted @ 2017-04-29 08:04  北北北北屿  阅读(162)  评论(0编辑  收藏  举报