bzoj2001 [Hnoi2010]City 城市建设 动态最小生成树
2017-04-13 17:31
323 查看
昨晚水冬令营课件看到这题,感觉蛮有意思的,学习了一波,抽象式理解,今天又看了大佬的代码,彻底弄懂了这个东西。
WC2013顾昱洲在《浅谈一类分治算法》中提到了动态最小生成树的分治做法,我来梳理下我的理解。
这个算法有两个重要的操作:
①reduction:
对于一张图,reduction操作的目的是删除一定不会出现在最小生成树中的边,以此减小图的规模
流程:
我们假设对于当前这张图,有k条边待修改,将这k条边权值设为inf,做最小生成树,易知此时不在最小生成树中的边是不会在任何修改后出现在最小生成树中的,所以将这些边删去,得到新图。
②contraction:
对于一张图,contraction操作的目的是将一定会出现在最小生成树中的边的缩起来,即将这些边两端点缩为一个点,减小图的规模。
流程:
假设对于当前这张图,有k条边待修改,将这k条边权值设为-inf,做最小生成树,易知此时仍在最小生成树中的边在任何修改后都会出现在最小生成树中吗,所以将这些边缩起来,得到新图。
好了,操作梳理完了,怎么利用这些操作解决问题呢?直接暴力模拟每个状态的图肯定是不行的,即使将图的规模缩小到了最少的k+1个点和2k条边,这个复杂度也是不能接受的。
但是显然可以发现,一条边的待修改状态存在于一个区间内,考虑同一张图P,对于在区间[l,r]中的修改进行reduction和contraction操作得到新图S,对在区间[x,y]中的修改进行reduction和contraction操作的到的新图T,若[x,y]∈[l,r],T必然是S的子图,所以用cdq分治即可。
代码:
WC2013顾昱洲在《浅谈一类分治算法》中提到了动态最小生成树的分治做法,我来梳理下我的理解。
这个算法有两个重要的操作:
①reduction:
对于一张图,reduction操作的目的是删除一定不会出现在最小生成树中的边,以此减小图的规模
流程:
我们假设对于当前这张图,有k条边待修改,将这k条边权值设为inf,做最小生成树,易知此时不在最小生成树中的边是不会在任何修改后出现在最小生成树中的,所以将这些边删去,得到新图。
②contraction:
对于一张图,contraction操作的目的是将一定会出现在最小生成树中的边的缩起来,即将这些边两端点缩为一个点,减小图的规模。
流程:
假设对于当前这张图,有k条边待修改,将这k条边权值设为-inf,做最小生成树,易知此时仍在最小生成树中的边在任何修改后都会出现在最小生成树中吗,所以将这些边缩起来,得到新图。
好了,操作梳理完了,怎么利用这些操作解决问题呢?直接暴力模拟每个状态的图肯定是不行的,即使将图的规模缩小到了最少的k+1个点和2k条边,这个复杂度也是不能接受的。
但是显然可以发现,一条边的待修改状态存在于一个区间内,考虑同一张图P,对于在区间[l,r]中的修改进行reduction和contraction操作得到新图S,对在区间[x,y]中的修改进行reduction和contraction操作的到的新图T,若[x,y]∈[l,r],T必然是S的子图,所以用cdq分治即可。
代码:
#include<bits/stdc++.h> #define ll long long #define inf 1ll<<50 #define N 100005 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,q,a ,sum[50]; int f ,c ;ll ans ; int find(int x){return x==f[x]?x:f[x]=find(f[x]);} struct node{int x,y;}p ; struct edge{int x,y,pos;ll c;}t ,e[50] ,d ; bool operator < (edge a,edge b){return a.c<b.c;} void clear(int x) { for(int i=1;i<=x;i++) f[d[i].x]=d[i].x, f[d[i].y]=d[i].y; } void contraction(int &tot,ll &adt) { int tmp=0; sort(d+1,d+1+tot);clear(tot); for(int i=1;i<=tot;i++) { int fx=find(d[i].x),fy=find(d[i].y); if(fx==fy)continue; f[fx]=fy;t[++tmp]=d[i]; } for(int i=1;i<=tmp;i++) f[t[i].x]=t[i].x, f[t[i].y]=t[i].y; for(int i=1;i<=tmp;i++) { if(t[i].c==-inf)continue; int fx=find(t[i].x),fy=find(t[i].y); adt+=t[i].c,f[fx]=fy; }tmp=0; for(int i=1;i<=tot;i++) { int fx=find(d[i].x),fy=find(d[i].y); if(fx==fy)continue; t[++tmp]=d[i]; t[tmp].x=find(d[i].x); t[tmp].y=find(d[i].y); c[d[i].pos]=tmp; }tot=tmp; for(int i=1;i<=tot;i++)d[i]=t[i]; } void reduction(int &tot) { sort(d+1,d+1+tot); clear(tot);int tmp=0; for(int i=1;i<=tot;i++) { int fx=find(d[i].x),fy=find(d[i].y); if(fx==fy) { if(d[i].c==inf) t[++tmp]=d[i],c[d[i].pos]=tmp; continue; }f[fx]=fy; t[++tmp]=d[i],c[d[i].pos]=tmp; }tot=tmp; for(int i=1;i<=tot;i++)d[i]=t[i]; } void solve(int l,int r,int now,ll adt) { int tot=sum[now]; if(l==r)a[p[l].x]=p[l].y; for(int j=1;j<=tot;j++) e[now][j].c=a[e[now][j].pos],d[j]=e[now][j],c[e[now][j].pos]=j; if(l==r) { clear(tot); sort(d+1,d+1+tot); for(int j=1;j<=tot;j++) { int fx=find(d[j].x),fy=find(d[j].y); if(fx==fy)continue; f[fx]=fy;adt+=d[j].c; }ans[l]=adt; return ; }int mid=(l+r)>>1; for(int i=l;i<=r;i++)d[c[p[i].x]].c=-inf; contraction(tot,adt); for(int i=l;i<=r;i++)d[c[p[i].x]].c=inf; reduction(tot); sum[now+1]=tot; for(int i=1;i<=tot;i++)e[now+1][i]=d[i]; solve(l,mid,now+1,adt); solve(mid+1,r,now+1,adt); } int main() { n=read(),m=read(),q=read(); for(int i=1;i<=m;i++) { e[0][i].x=read(),e[0][i].y=read(); e[0][i].pos=i,a[i]=e[0][i].c=read(); }sum[0]=m; for(int i=1;i<=q;i++) p[i].x=read(),p[i].y=read(); solve(1,q,0,0); for(int i=1;i<=q;i++) printf("%lld\n",ans[i]); }
相关文章推荐
- [动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设
- 【BZOJ】2001 [Hnoi2010]City 城市建设 cdq分治——动态最小生成树
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- [动态MST] [CDQ分治] BZOJ2001: [Hnoi2010]City 城市建设
- BZOJ 2001 [Hnoi2010]City 城市建设 LCT+分治(未成功卡时卡过)
- bzoj 2001 [Hnoi2010]City 城市建设
- 【BZOJ2001】[Hnoi2010]City 城市建设
- BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】
- bzoj2001【HNOI2010】City 城市建设
- BZOJ 2001: [Hnoi2010]City 城市建设
- [bzoj2001][Hnoi2010][City 城市建设] (cdq分治)
- 【HNOI2010】【BZOJ2001】City 城市建设2015.4.9编辑修改
- bzoj2001 [Hnoi2010]City 城市建设
- bzoj2001: [Hnoi2010]City 城市建设
- bzoj2001: [Hnoi2010]City 城市建设 wikioi2332
- BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治
- BZOJ 2001: [Hnoi2010]City 城市建设
- bzoj 2001: [Hnoi2010]City 城市建设
- bzoj2001 [Hnoi2010]City 城市建设