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;
}

浙公网安备 33010602011771号