题意:(说不清)
一道证明复杂度题
这样是
O(mm−−√log2n)
的
自己看吧~
#include<bits/stdc++.h>
#define LEN 300000
using namespace std;
inline int getint(){
int x=0,p=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-')p=-1;
c=getchar();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x*p;
}
struct road{
int u,v;
}r[LEN];
vector<int>r2[LEN];
int d[LEN];
inline void work(){
int n=getint(),m=getint();
for(int i=0;i<=n+1;++i){
r2[i].clear();
d[i]=0;
}
for(int i=0;i<=m+1;++i){
r[i].u=r[i].v=0;
}
#if n==30
#define int char
#endif
for(int i=1;i<=m;++i){
int u=getint(),v=getint();
r[i].u=u,r[i].v=v;
r2[u].push_back(v);
r2[v].push_back(u);
++d[u],++d[v];
}
for(int i=1;i<=n;++i){
sort(r2[i].begin(),r2[i].end());
}
long long ans=0;
for(int i=1;i<=m;++i){
int u=r[i].u,v=r[i].v;
if(d[u]>d[v])swap(u,v);
int tot=0;
vector<int>::iterator xx=r2[v].begin();
for(int j=0;j<d[u];++j){
if((xx=lower_bound(xx,r2[v].end(),r2[u][j]))!=r2[v].end()&&*xx==r2[u][j]){
++tot;
}
if(xx==r2[v].end())break;
}
ans+=(long long)tot*(tot-1)/2;
}
cout<<ans<<"\n";
}
int main(){
int t=getint();
while(t--){
work();
}
return 0;
}
好吧,证一下复杂度。
将点分为两类,度数
<n√
<script type="math/tex" id="MathJax-Element-4918"><\sqrt n</script>的叫轻点,反之叫重点
易得重点不超过
O(n√)
个
对于所有有至少一端为轻点的边,每次查询复杂度为
O(n√log2n)
的
对于所有连接两个重点的边,我们考虑每个黑点被作为代码中的
v
的时后,最多会枚举所有度数比它小的所有点的所有边,总边数不超过
证毕