NOIP模拟(20171030)T3 星星

来源:互联网 发布:mac dance with me唇釉 编辑:程序博客网 时间:2024/05/15 15:36

题意:(说不清)
一道证明复杂度题
这样是O(mmlog2n)
自己看吧~

#include<bits/stdc++.h>#define LEN 300000using 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的叫轻点,反之叫重点
易得重点不超过O(n)
对于所有有至少一端为轻点的边,每次查询复杂度为O(nlog2n)
对于所有连接两个重点的边,我们考虑每个黑点被作为代码中的v 的时后,最多会枚举所有度数比它小的所有点的所有边,总边数不超过m,共O(n)个黑点,故总复杂度为O(nlog2n)
证毕