[动态MST] [CDQ分治] BZOJ2001: [Hnoi2010]City 城市建设
2017-07-11 22:53
411 查看
题意
PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。题解
这个题目是每次修改边权,需要你马上求出全局的MST。改变一条边后对MST的影响是很大的,显然要往CDQ分治的方面想。
一般的CDQ分治都是考虑左边的修改对右边询问的贡献,但是这道题的这个贡献很难简单表达。
所以这里用了一个很特殊的思路:分治时不断重建图使得图的规模变小,保证复杂度。
大概就是:
void Solve(L,R){ if(L==R){ 直接计算ans[L]; return; } 干一些奥妙重重的事情缩图; Solve(L,mid); Solve(mid+1,R); }
为了方便表述,对于 [L,R] 所有操作修改到的边,我们称作修改边,修改边的集合为 S,|S|≤R−L+1。
缩图有这样两个核心操作:
Reduction:
把修改边的边权暂且记为 INF ,对全图刷 MST ,不在这个 MST 中的边,不管之后修改的边权为多少,一定是没用的,直接扔掉。
显然用这个操作可以使边数不超过 |S|+n−1 。
Contraction:
把修改边的边权暂且记为 −INF ,对全图刷 MST,在这个MST中的非修改边,不管之后修改的边权为多少,都是必须要选的。
把这些边连上后,把一块连通的点缩在一起。
这个操作可以使点数不超过 n−((n−1)−|S|)=|S|+1 。
上述两个操作的复杂度都为O(mlogm)。
所以我们执行 Contraction−Reduction,图的规模就从 (n,m) 变成 (|S|+1,2|S|) 了!
然后就好了,复杂度为O(mlog2m)。
有点难写,于是参考了网上很多dalao的代码,后来改来改去都写的几乎一样了…
#include<cstdio> #include<algorithm> #define Fir first #define Sec second using namespace std; typedef long long LL; const int maxn=20005,maxq=50005,maxe=50005; int w[maxe]; LL ans[maxq]; struct Edge{ int x,y,w,id; bool operator < (const Edge &B)const{ return w<B.w; } } e[25][maxe],tmp[maxe],t_e[maxe]; pair<int,int> q[maxq]; int fa[maxn],t_id[maxn]; bool vis[maxn]; int getfa(int x){ fa[x]=fa[x]==x?x:fa[x]=getfa(fa[x]); } void merge(int x,int y){ x=getfa(x); y=getfa(y); if(x!=y) fa[x]=y; } void Contraction(int &_n,int &_m,LL &res){ int n_now=0,m_now=0; for(int i=1;i<=_n;i++) fa[i]=i; sort(tmp+1,tmp+1+_m); for(int i=1;i<=_m;i++){ if(getfa(tmp[i].x)!=getfa(tmp[i].y)) merge(tmp[i].x,tmp[i].y), t_e[++m_now]=tmp[i]; } for(int i=1;i<=_n;i++) fa[i]=i; for(int i=1;i<=m_now;i++) if(t_e[i].w!=-1e+9&&getfa(t_e[i].x)!=getfa(t_e[i].y)) merge(t_e[i].x,t_e[i].y), res+=t_e[i].w; for(int i=1;i<=_n;i++) vis[i]=false; for(int i=1;i<=_n;i++) if(!vis[getfa(i)]) vis[getfa(i)]=true, t_id[getfa(i)]=++n_now; m_now=0; for(int i=1;i<=_m;i++) if(getfa(tmp[i].x)!=getfa(tmp[i].y)){ t_e[++m_now]=tmp[i]; t_e[m_now].x=t_id[getfa(tmp[i].x)]; t_e[m_now].y=t_id[getfa(tmp[i].y)]; } for(int i=1;i<=m_now;i++) tmp[i]=t_e[i]; _n=n_now; _m=m_now; } void Reduction(int _n,int &_m){ for(int i=1;i<=_n;i++) fa[i]=i; sort(tmp+1,tmp+1+_m); int m_now=0; for(int i=1;i<=_m;i++){ if(getfa(tmp[i].x)!=getfa(tmp[i].y)){ merge(tmp[i].x,tmp[i].y); t_e[++m_now]=tmp[i]; } else if(tmp[i].w==1e+9) t_e[++m_now]=tmp[i]; } for(int i=1;i<=m_now;i++) tmp[i]=t_e[i]; _m=m_now; } int pos[maxe]; void Solve(int L,int R,int k,int _n,int _m,LL res){ if(L==R) w[q[L].Fir]=q[L].Sec; for(int i=1;i<=_m;i++) e[k][i].w=w[e[k][i].id]; for(int i=1;i<=_m;i++) tmp[i]=e[k][i]; if(L==R){ for(int i=1;i<=_n;i++) fa[i]=i; sort(tmp+1,tmp+1+_m); for(int i=1;i<=_m;i++) if(getfa(tmp[i].x)!=getfa(tmp[i].y)){ merge(tmp[i].x,tmp[i].y); res+=tmp[i].w; } ans[L]=res; return; } for(int i=1;i<=_m;i++) pos[tmp[i].id]=i; for(int i=L;i<=R;i++) tmp[pos[q[i].Fir]].w=-1e+9; Contraction(_n,_m,res); for(int i=1;i<=_m;i++) pos[tmp[i].id]=i; for(int i=L;i<=R;i++) tmp[pos[q[i].Fir]].w=1e+9; Reduction(_n,_m); for(int i=1;i<=_m;i++) e[k+1][i]=tmp[i]; int mid=(L+R)>>1; Solve(L,mid,k+1,_n,_m,res); Solve(mid+1,R,k+1,_n,_m,res); } int n,m,Q; int main(){ freopen("bzoj2001.in","r",stdin); freopen("bzoj2001.out","w",stdout); scanf("%d%d%d",&n,&m,&Q); for(int i=1;i<=m;i++){ scanf("%d%d%d",&e[0][i].x,&e[0][i].y,&e[0][i].w); w[e[0][i].id=i]=e[0][i].w; } for(int i=1;i<=Q;i++) scanf("%d%d",&q[i].Fir,&q[i].Sec); Solve(1,Q,0,n,m,0); for(int i=1;i<=Q;i++) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- 【BZOJ】2001 [Hnoi2010]City 城市建设 cdq分治——动态最小生成树
- [动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治
- [bzoj2001][Hnoi2010][City 城市建设] (cdq分治)
- BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- BZOJ 2001 [Hnoi2010]City 城市建设 LCT+分治(未成功卡时卡过)
- [BZOJ2001][HNOI2010]City城市建设-CDQ分治
- bzoj2001 [Hnoi2010]City 城市建设 动态最小生成树
- 【bzoj2001】 Hnoi2010—City 城市建设
- 【bzoj2001】[Hnoi2010]City 城市建设
- 【HNOI2010】【BZOJ2001】City 城市建设2015.4.9编辑修改
- BZOJ 2001 Hnoi2010 城市建设 分治+LCT
- 【BZOJ2001】[Hnoi2010]City 城市建设
- bzoj2001【HNOI2010】City 城市建设
- bzoj2001: [Hnoi2010]City 城市建设
- bzoj2001: [Hnoi2010]City 城市建设 wikioi2332
- [BZOJ2001][Hnoi2010]City 城市建设(CDQ分治+并查集)
- 2001: [Hnoi2010]City 城市建设 - BZOJ