zoukankan      html  css  js  c++  java
  • cf1089d Distance Sum

    题目大意

    给一个有n个点,m条边的无向连通图,求所有点两两之间的最短路。$(2<=n<=10^5;n-1<=m<=n+42)$

    solution

    我们注意到$m-n+1$很小。先任意求一棵生成树,然后将剩余$m-n+1$条边涉及的点建一棵虚树。分类讨论如下情况即可:

    (1)不属于虚树上任意一条边的点到所有点的贡献;单次操作$O(1)$(合并到虚树边上的点)

    (2)一个点到同一条边内其它点的最短路和(非关键点);单次操作$O(1)$

    (3)一个在虚树上某条边的点(包括关键点)到其它边内非关键点的贡献。单次操作$O(m-n+1)$

    (4)关键点到关键点的最短路和。$O((m-n+1)*$最短路复杂度$)$

    用前缀和和后缀和优化即可,时间复杂度为$O(m(m-n+1))$。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define ot original_tree
      6 #define vt virtual_tree
      7 typedef long long ll;
      8 const int LEN=2000000;
      9 char str[2000010];int pos=0;
     10 inline int rd(){
     11     char c=str[pos++];int x=0,flag=1;
     12     for(;c<'0'||c>'9';c=str[pos++])if(c=='-')flag=-1;
     13     for(;c>='0'&&c<='9';c=str[pos++])x=x*10+c-'0';
     14     return x*flag;
     15 }
     16 const int N=120010,M=1010;
     17 int n,m;ll ans=0;
     18 inline int min_(int x,int y){
     19     return (x<=y)?x:y;
     20 }
     21 namespace original_tree{
     22     struct tree{int dep,dfn,sz,fa[20];}t[N];
     23     struct edge{int to,nxt;}e[N<<1];
     24     int tim=0,cur[N]={0},head[N]={0};
     25     bool tag[N]={false};
     26     void dfs(int u){
     27         for(int i=1;i<20;i++)
     28             t[u].fa[i]=t[t[u].fa[i-1]].fa[i-1];
     29         t[u].sz=1;cur[t[u].dfn=++tim]=u;
     30         for(int i=head[u];i;i=e[i].nxt){
     31             int v=e[i].to;
     32             if(t[v].sz)
     33                 continue;
     34             tag[(i>m)?i-m:i]=true;
     35             t[v].dep=t[u].dep+1;
     36             t[v].fa[0]=u;dfs(v);
     37             t[u].sz+=t[v].sz;
     38         }
     39         return;
     40     }
     41     void build(){
     42         memset(t,0,sizeof(t));
     43         for(int i=1;i<=m;i++){
     44             int u=rd(),v=rd();
     45             e[i]=(edge){v,head[u]};head[u]=i;
     46             e[m+i]=(edge){u,head[v]};head[v]=m+i;
     47         }
     48         dfs(1);
     49         return;
     50     }
     51     inline int lca(int u,int v){
     52         if(t[u].dep<t[v].dep)
     53             swap(u,v);
     54         int delta=t[u].dep-t[v].dep;
     55         for(int i=0;i<20;i++)
     56             if(delta&(1<<i))
     57                 u=t[u].fa[i];
     58         for(int i=19;~i;i--)
     59             if(t[u].fa[i]!=t[v].fa[i]){
     60                 u=t[u].fa[i];
     61                 v=t[v].fa[i];
     62             }
     63         return (u==v)?u:t[u].fa[0];
     64     }
     65     void solve(int u){
     66         for(int i=head[u];i;i=e[i].nxt){
     67             int v=e[i].to;
     68             if(u!=t[v].fa[0])
     69                 continue;
     70             ans+=(ll)t[v].sz*(n-t[v].sz);
     71             solve(v);
     72         }
     73         return;
     74     }
     75 }
     76 namespace virtual_tree{
     77     struct edge{int to,nxt,dis;}e[M<<1];
     78     int cnt=0,head[M]={0};bool inv[N]={false};
     79     int num=0,vid[M],id[N]={0},fa[M]={0};
     80     int top=0,st[M];bool choose[N]={false};
     81     int dis[M][M];bool inq[M]={false};
     82     ll pre[N]={0},suf[N]={0},p[N]={0},s[N]={0};
     83     int sz[N]={0},len[M],vis[N]={0};
     84     int ql,qr,q[N];
     85     inline void link(int u,int v,int w){
     86         e[++cnt]=(edge){v,head[u],w};
     87         head[u]=cnt;
     88         e[++cnt]=(edge){u,head[v],w};
     89         head[v]=cnt;
     90         return;
     91     }
     92     void build(){
     93         for(int i=1;i<=m;i++)
     94             if(!ot::tag[i]){
     95                 choose[ot::e[i].to]=true;
     96                 choose[ot::e[m+i].to]=true;
     97             }
     98         vid[id[st[++top]=1]=++num]=1;
     99         for(int i=2;i<=n;i++){
    100             int x=ot::cur[i];
    101             if(!choose[x])
    102                 continue;
    103             int pre=ot::lca(x,st[top]);
    104             for(;top>1&&ot::t[st[top-1]].dep>=ot::t[pre].dep;top--){
    105                 link(id[st[top]],id[st[top-1]],ot::t[st[top]].dep-ot::t[st[top-1]].dep);
    106                 fa[id[st[top]]]=id[st[top-1]];
    107             }
    108             if(st[top]!=pre){
    109                 link(id[st[top]],id[pre]=++num,ot::t[st[top]].dep-ot::t[pre].dep);
    110                 fa[id[st[top]]]=id[pre];vid[num]=st[top]=pre;
    111             }
    112             vid[id[st[++top]=x]=++num]=x;
    113         }
    114         for(int i=top;i>1;i--){
    115             link(id[st[i]],id[st[i-1]],ot::t[st[i]].dep-ot::t[st[i-1]].dep);
    116             fa[id[st[i]]]=id[st[i-1]];
    117         }
    118         for(int i=1;i<=m;i++)
    119             if(!ot::tag[i])
    120                 link(id[ot::e[i].to],id[ot::e[m+i].to],1);
    121         return;
    122     }
    123     void spfa(){
    124         memset(dis,0x3f,sizeof(dis));
    125         for(int x=1;x<=num;x++){
    126             q[ql=qr=1]=x;dis[x][x]=0;inq[x]=true;
    127             while(ql<=qr){
    128                 int u=q[ql++];inq[u]=false;
    129                 for(int i=head[u];i;i=e[i].nxt){
    130                     int v=e[i].to;
    131                     if(dis[x][v]>dis[x][u]+e[i].dis){
    132                         dis[x][v]=dis[x][u]+e[i].dis;
    133                         if(!inq[v])
    134                             inq[q[++qr]=v]=true;
    135                     }
    136                 }
    137             }
    138         }
    139         return;
    140     }
    141     void solve(){
    142         for(int i=2;i<=num;i++)
    143             for(int u=vid[i];u!=vid[fa[i]];u=ot::t[u].fa[0])
    144                 inv[u]=true;
    145         inv[1]=true;
    146         for(int u=1;u<=n;u++){
    147             if(!inv[u])
    148                 continue;
    149             sz[u]=1;
    150             for(int i=ot::head[u];i;i=ot::e[i].nxt){
    151                 int v=ot::e[i].to,pos=ot::t[v].sz;
    152                 if(inv[v])
    153                     continue;
    154                 ans+=(ll)pos*(n-pos);sz[u]+=pos;
    155                 ot::solve(v);
    156             }
    157         }
    158         for(int i=2;i<=num;i++)
    159             len[i]=ot::t[vid[i]].dep-ot::t[vid[fa[i]]].dep-1;
    160         for(int x=2;x<=num;x++){
    161             if(!len[x])continue;
    162             pre[len[x]+1]=p[len[x]+1]=suf[len[x]+1]=s[len[x]+1]=0;
    163             for(int i=1,u=ot::t[vid[x]].fa[0];i<=len[x];i++,u=ot::t[u].fa[0])
    164                 pre[i]=pre[i-1]+(ll)i*sz[u],p[i]=p[i-1]+sz[u];
    165             for(int i=1,u=ot::t[vid[x]].fa[0];i<=len[x];i++,u=ot::t[u].fa[0])
    166                 suf[i]=(ll)(len[x]-i+1)*sz[u],s[i]=sz[u];
    167             for(int i=len[x]-1;i;i--)
    168                 suf[i]+=suf[i+1],s[i]+=s[i+1];
    169             int dist=dis[x][fa[x]],dep1=ot::t[vid[x]].dep;ll val=0;
    170             for(int u=ot::t[vid[x]].fa[0];u!=vid[fa[x]];u=ot::t[u].fa[0]){
    171                 int now=dep1-ot::t[u].dep,d=min_(now,len[x]-now+1);ll res=0;
    172                 res+=pre[now+d-1]-pre[now-1]-(p[now+d-1]-p[now-1])*now;
    173                 res+=suf[now-d+1]-suf[now+1]-(s[now-d+1]-s[now+1])*(len[x]-now+1);
    174                 if(now==len[x]-now+1){
    175                     val+=res*sz[u];
    176                     continue;
    177                 }
    178                 int l=now-d,r=now+d;
    179                 if(r==len[x]+1){
    180                     if(l<=dist+1)
    181                         res+=suf[1]-suf[l+1]-(s[1]-s[l+1])*(len[x]-now+1);
    182                     else{
    183                         int h=(l-dist-1)>>1,tg=(l-dist-1)&1;
    184                         res+=pre[h+tg]+p[h+tg]*(len[x]-now+1+dist);
    185                         res+=suf[l-dist-h]-suf[l+1]-(s[l-dist-h]-s[l+1])*(len[x]-now+1);
    186                     }
    187                 }
    188                 else{
    189                     if(len[x]-r+1<=dist+1)
    190                         res+=pre[len[x]]-pre[r-1]-(p[len[x]]-p[r-1])*now;
    191                     else{
    192                         int h=(len[x]-r-dist)>>1,tg=(len[x]-r-dist)&1;
    193                         res+=pre[r+dist+h]-pre[r-1]-(p[r+dist+h]-p[r-1])*now;
    194                         res+=suf[len[x]-h-tg+1]+s[len[x]-h-tg+1]*(now+dist);
    195                     }
    196                 }
    197                 val+=res*sz[u];
    198             }//point in the same edge
    199             ans+=val>>1;
    200             for(int y=2;y<x;y++){
    201                 int dist1=0,dist2=len[y]+1;
    202                 for(int u=ot::t[vid[y]].fa[0];u!=vid[fa[y]];u=ot::t[u].fa[0]){
    203                     ll val=0;dist1++;dist2--;
    204                     int dis1=min_(dist1+dis[x][y],dist2+dis[x][fa[y]]);
    205                     int dis2=min_(dist1+dis[fa[x]][y],dist2+dis[fa[x]][fa[y]]);
    206                     int d=abs(dis1-dis2);
    207                     if(d>=len[x]){
    208                         if(dis1<=dis2)
    209                             ans+=(pre[len[x]]+p[len[x]]*dis1)*sz[u];
    210                         else
    211                             ans+=(suf[1]+s[1]*dis2)*sz[u];
    212                         continue;
    213                     }
    214                     int h=(len[x]-d)>>1,tg=(len[x]-d)&1;
    215                     if(dis1<=dis2){
    216                         val+=pre[d+h+tg]+p[d+h+tg]*dis1;
    217                         val+=suf[len[x]-h+1]-suf[len[x]+1]+(s[len[x]-h+1]-s[len[x]+1])*dis2;
    218                     }
    219                     else{
    220                         val+=pre[h+tg]+p[h+tg]*dis1;
    221                         val+=suf[len[x]-d-h+1]+s[len[x]-d-h+1]*dis2;
    222                     }
    223                     ans+=val*sz[u];
    224                 }
    225             }//edge to edge
    226             for(int i=1;i<=num;i++){
    227                 int dis1=dis[x][i],dis2=dis[fa[x]][i];
    228                 int d=abs(dis1-dis2);ll val=0;
    229                 if(d>=len[x]){
    230                     if(dis1<=dis2)
    231                         ans+=(pre[len[x]]+p[len[x]]*dis1)*sz[vid[i]];
    232                     else
    233                         ans+=(suf[1]+s[1]*dis2)*sz[vid[i]];
    234                     continue;
    235                 }
    236                 int h=(len[x]-d)>>1,tg=(len[x]-d)&1;
    237                 if(dis1<=dis2){
    238                     val+=pre[d+h+tg]+p[d+h+tg]*dis1;
    239                     val+=suf[len[x]-h+1]-suf[len[x]+1]+(s[len[x]-h+1]-s[len[x]+1])*dis2;
    240                 }
    241                 else{
    242                     val+=pre[h+tg]+p[h+tg]*dis1;
    243                     val+=suf[len[x]-d-h+1]+s[len[x]-d-h+1]*dis2;
    244                 }
    245                 ans+=val*sz[vid[i]];
    246             }//key point to edge
    247         }
    248         for(int i=1;i<num;i++)
    249             for(int j=i+1;j<=num;j++)
    250                 ans+=(ll)sz[vid[i]]*sz[vid[j]]*dis[i][j];
    251         return;
    252     }
    253 }
    254 int main(){
    255     fread(str,1,LEN,stdin);
    256     n=rd();m=rd();ot::build();
    257     vt::build();vt::spfa();
    258     vt::solve();
    259     printf("%lld
    ",ans);
    260     return 0;
    261 }
  • 相关阅读:
    Choosing the Type at Runtime
    User-Defined Components Must Be Capitalized
    Computed property names
    Controlled Components
    Handling Event
    State
    props
    Functional and Class Components
    招聘漂亮的员工
    Spread Syntax
  • 原文地址:https://www.cnblogs.com/gzez181027/p/cf1089d.html
Copyright © 2011-2022 走看看