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\n",ans); 260 return 0; 261 }