zoukankan      html  css  js  c++  java
  • [nowcoder5669J]Jumping on the Graph

    考虑枚举$k$并求出$f(k)=sum_{i=1}^{n}limitssum_{j=i+1}^{n}limits [D(i,j)le k]$,那么答案就是$sum_{i=1}^{1e9}(f(i)-f(i-1))cdot i$
    考虑如何求出$a_{k}$:将大于$k$的边标成1,小于等于$k$的边标成0,令$L(i,j)$表示新图中两点间的最短路,那么$D(i,j)le k$当且仅当$L(i,j)le 1$
    可以有这样一个算法,从小到大枚举$k$,并将边权为0的边所构成的连通块缩点,记连通块大小分别为$a_{1},a_{2},...,a_{n'}$,两个连通块之间的边集合为$E$(删去重边自环),那么答案为$sum_{i=1}^{n'}c(a_{i},2)+sum_{(i,j)in E}a_{i}cdot a_{j}$
    考虑维护$k$变大所带来的影响,即将一条边权为1的边改为0:设这条边相连的两个连通块为$x$和$y$($x e y$),则有变化量$且Delta=a_{y}sum_{(i,x)in E}a_{i}+a_{x}sum_{(i,y)in E}a_{i}-(a_{x}+a_{y})sum_{(i,x)in E且(i,y)in E}a_{i}$,由于每一条初始的边最多对应新图中的一条边,因此仍然可以暴力存储每一个点的出边并启发式合并,然后对$x$和$y$的连通块大小分类讨论:
    1.$a_{x},a_{y}le sqrt{M}$或$sqrt{M}le a_{x},a_{y}$,暴力枚举即可(第二类最多只出现$sqrt{M}$次)
    2.$a_{x}le sqrt{M}le a_{y}$(交换同理),那么对于$sqrt{M}le a_{y}$需要预处理出$s_{y}=sum_{i=1}^{n}[(i,y)in E]cdot a_{i}$(要预处理的$s$最多$sqrt{M}$个),并用$set$维护出边集合来支持查找
    复杂度分析,包括预处理和计算:预处理,包括出边的$set$和$sqrt{M}$个点的$s$,$s$的修改可以暴力枚举每一个点是否要修改,复杂度为$o(Msqrt{M}+Mlog^{2}M)$;计算,1为$o(Msqrt{M})$,2为$o(Mlog M)$(由于每一个数最多作为$a_{x}$参与一次),总复杂度即为$o(Msqrt{M}+Mlog^{2}M)$
    具体实现细节较多,可能会有很多地方需要修改,详见代码
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 struct ji{
     5     int x,y,z;
     6 }e[N<<1];
     7 vector<int>v;
     8 set<int>s[N];
     9 set<int>::iterator it;
    10 int K,n,m,sz[N],f[N],tot[N];
    11 long long ans;
    12 bool cmp(ji x,ji y){
    13     return x.z<y.z;
    14 }
    15 int find(int k){
    16     if (k==f[k])return k;
    17     return f[k]=find(f[k]);
    18 }
    19 int calc(int k){
    20     if (tot[k])return tot[k];
    21     int ans=0;
    22     for(it=s[k].begin();it!=s[k].end();it++)ans+=sz[(*it)];
    23     return ans;
    24 }
    25 int main(){
    26     scanf("%d%d",&n,&m);
    27     for(int i=1;i<=m;i++){
    28         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
    29         if (e[i].x!=e[i].y){
    30             s[e[i].x].insert(e[i].y);
    31             s[e[i].y].insert(e[i].x);
    32         }
    33     }
    34     sort(e+1,e+m+1,cmp);
    35     K=400;
    36     for(int i=1;i<=n;i++){
    37         f[i]=i;
    38         sz[i]=1;
    39     }
    40     for(int i=1;i<=n;i++)
    41         if (s[i].size()>K){
    42             tot[i]=calc(i);
    43             v.push_back(i);
    44         }
    45     for(int i=1;i<=m;i++){
    46         int x=find(e[i].x),y=find(e[i].y);
    47         if (x==y)continue;
    48         if ((tot[x])&&(!tot[y]))swap(x,y);
    49         long long sum=1LL*sz[x]*(calc(y)-sz[x]);
    50         for(it=s[x].begin();it!=s[x].end();it++){
    51             s[(*it)].erase(x);
    52             if ((*it)==y)continue;
    53             sum+=1LL*sz[y]*sz[(*it)];
    54             if (tot[(*it)])tot[(*it)]-=sz[x];
    55             if (s[y].find((*it))!=s[y].end())sum-=1LL*(sz[x]+sz[y])*sz[(*it)];
    56             else{
    57                 s[y].insert((*it));
    58                 if (tot[y])tot[y]+=sz[(*it)];
    59                 s[(*it)].insert(y);
    60                 if (tot[(*it)])tot[(*it)]+=sz[y];
    61             }
    62         }
    63         if (tot[y])tot[y]-=sz[x];
    64         if ((!tot[y])&&(s[y].size()>K)){
    65             tot[y]=calc(y);
    66             v.push_back(y);
    67         }
    68         f[x]=y;
    69         sz[y]+=sz[x];
    70         ans+=sum*e[i].z;
    71         if (tot[x])
    72             for(int j=0;j<v.size();j++)
    73                 if (v[j]==x){
    74                     for(int k=j;k;k--)swap(v[k],v[k-1]);
    75                     v.erase(v.begin());
    76                     break;
    77                 }
    78         s[x].clear();
    79         for(int j=0;j<v.size();j++)
    80             if ((v[j]!=y)&&(s[y].find(v[j])!=s[y].end()))tot[v[j]]+=sz[x];
    81         sz[x]=0;
    82     }
    83     printf("%lld",ans);
    84 }
    View Code
  • 相关阅读:
    切换到真正的最高权限 SYSTEM 账户界面
    javascript中replace的正则表达式语法
    微软系统漏洞_超长文件路径打造私人地盘
    JAVA控制台
    PowerPoint绘图笔不能用
    《JavaScript核心技术》
    Catch(...) C++中三个点
    XMLHttp连续调用SEND需要注意的问题
    Wscript中的事件机制
    JavaScript(JS)常用的正则表达式
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13404650.html
Copyright © 2011-2022 走看看