[关闭]
@ysner 2018-09-29T08:24:47.000000Z 字数 2857 阅读 1957

[bzoj2238]Mst

生成树 最小生成树 图论 树链剖分 线段树


题面

给出一个个点条边的无向带权图,以及个询问,每次询问在图中删掉一条边后图的最小生成树。(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的边在下一条询问中依然存在)

解析

很显然题目是问我们一条边被删掉后,能替代它的边的最小长度是多少。

首先构出一棵最小生成树,
如果边不在树内,直接输出最小生成树边权和就可以了。
然后考虑边在树内应该怎么处理。

有一个比较容易想到的结论:一条非树边,肯定能够完全替代,该边两端点在树上的路径中包含的所有边。
于是把边权化为更深结点的点权,然后树链剖分+线段树,用所有非树边对树边覆盖取即可。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<queue>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define ls x<<1
  12. #define rs x<<1|1
  13. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  14. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  15. using namespace std;
  16. const int N=5e5+100;
  17. int n,m,q,h[N],cnt,f[N],tot,F[N],d[N],top[N],L[N],R[N],sz[N],tim,id[N],t[N<<2],w[N],tag[N<<2],son[N];
  18. ll s,gu;
  19. struct Edge{int to,nxt,w;}e[N<<1];
  20. struct dat{int u,v,w,bei,id;il bool operator < (const dat &o) const {return w<o.w;}}a[N<<1];
  21. il void add(re int u,re int v,re int w)
  22. {
  23. e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;
  24. e[++cnt]=(Edge){u,h[v],w};h[v]=cnt;
  25. }
  26. il void dfs1(re int u,re int fa)
  27. {
  28. f[u]=fa;d[u]=d[fa]+1;sz[u]=1;
  29. for(re int i=h[u];i+1;i=e[i].nxt)
  30. {
  31. re int v=e[i].to;
  32. if(v==fa) continue;
  33. dfs1(v,u);
  34. sz[u]+=sz[v];
  35. if(sz[v]>sz[son[u]]) son[u]=v;
  36. }
  37. }
  38. il void dfs2(re int u,re int up)
  39. {
  40. top[u]=up;L[u]=++tim;id[tim]=u;
  41. if(son[u]) dfs2(son[u],up);
  42. for(re int i=h[u];i+1;i=e[i].nxt)
  43. {
  44. re int v=e[i].to;
  45. if(v==f[u]||v==son[u]) continue;
  46. dfs2(v,v);
  47. }
  48. R[u]=tim;
  49. }
  50. il void Modify(re int x,re int l,re int r,re int ql,re int qr,re int w)
  51. {
  52. if(ql<=l&&r<=qr) {t[x]=min(t[x],w);tag[x]=min(tag[x],w);return;}
  53. re int mid=l+r>>1;
  54. if(ql<=mid) Modify(ls,l,mid,ql,qr,w);
  55. if(qr>mid) Modify(rs,mid+1,r,ql,qr,w);
  56. t[x]=min(tag[x],min(t[ls],t[rs]));
  57. }
  58. il int Query(re int x,re int l,re int r,re int pos)
  59. {
  60. if(l==r) return t[x];
  61. re int mid=l+r>>1;
  62. if(pos<=mid) return min(tag[x],Query(ls,l,mid,pos));
  63. return min(tag[x],Query(rs,mid+1,r,pos));
  64. }
  65. il int find(re int x){return x==F[x]?x:F[x]=find(F[x]);}
  66. il ll gi()
  67. {
  68. re ll x=0,t=1;
  69. re char ch=getchar();
  70. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  71. if(ch=='-') t=-1,ch=getchar();
  72. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  73. return x*t;
  74. }
  75. il bool cmp(re dat x,re dat y){return x.id<y.id;}
  76. int main()
  77. {
  78. memset(h,-1,sizeof(h));
  79. n=gi();m=gi();
  80. fp(i,1,n) F[i]=i;
  81. fp(i,1,m) a[i].u=gi(),a[i].v=gi(),a[i].w=gi(),a[i].id=i;
  82. q=gi();
  83. sort(a+1,a+1+m);
  84. fp(i,1,m)
  85. {
  86. re int u=a[i].u,fu=find(u),v=a[i].v,fv=find(v),w=a[i].w;
  87. if(fu^fv) F[fv]=fu,add(u,v,w),s+=w,++gu;
  88. else a[i].bei=1;
  89. }
  90. if(gu<n-1) {while(q--) puts("Not connected");return 0;}
  91. dfs1(1,0);dfs2(1,1);
  92. sort(a+1,a+1+m,cmp);
  93. memset(t,127,sizeof(t));memset(tag,127,sizeof(tag));
  94. fp(i,1,m)
  95. if(a[i].bei)
  96. {
  97. re int u=a[i].u,v=a[i].v,w=a[i].w;
  98. while(top[u]^top[v])
  99. {
  100. if(d[top[u]]<d[top[v]]) swap(u,v);
  101. Modify(1,1,n,L[top[u]],L[u],w);
  102. u=f[top[u]];
  103. }
  104. if(d[u]>d[v]) swap(u,v);
  105. if(u^v) Modify(1,1,n,L[u]+1,L[v],w);
  106. }
  107. while(q--)
  108. {
  109. re int x=gi();
  110. if(a[x].bei) {printf("%lld\n",s);continue;}
  111. re int ans=Query(1,1,n,L[(d[a[x].u]>d[a[x].v]?a[x].u:a[x].v)]);
  112. if(ans==t[0]) {puts("Not connected");continue;}
  113. printf("%lld\n",s-a[x].w+ans);
  114. }
  115. return 0;
  116. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注