[BZOJ2001][HNOI2010]City城市建设-CDQ分治
来源:互联网 发布:竞价优化 编辑:程序博客网 时间:2024/06/06 03:47
City 城市建设
Description
PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。
Input
文件第一行包含三个整数N,M,Q,分别表示城市的数目,可以修建的道路个数,及收到的消息个数。
接下来M行,第i+1行有三个用空格隔开的整数Xi,Yi,Zi(1≤Xi,Yi≤n, 0≤Zi≤50000000),表示在城市Xi与城市Yi之间修建道路的代价为Zi。
接下来Q行,每行包含两个数k,d,表示输入的第k个道路的修建代价修改为d(即将Zk修改为d)。
Output
输出包含Q行,第i行输出得知前i条消息后使城市连通的最小花费总和。
Sample Input
5 5 3
1 2 1
2 3 2
3 4 3
4 5 4
5 1 5
1 6
1 1
5 3
Sample Output
14
10
9
HINT
【数据规模】
对于20%的数据, n≤1000,m≤6000,Q≤6000。
有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。
对于100%的数据, n≤20000,m≤50000,Q≤50000。
啊咱为什么要做这道题……
感觉调到最后意识模糊完全是在对着标程改……
(╯‵□′)╯︵┻━┻
思路:
首先,考虑最小生成树的性质。
本质上,最小生成树是个贪心(咱在知乎上看到过到底是贪心还是DP的讨论)。
那么每一时刻它都将会选择当前局部最优解。
那么,从prim的角度思考:
如果咱把一些点看成一个点集S。
考虑对整个图做最小生成树T。
那么所有不在T上的、在S的补集内部连接的所有边都将毫无意义。
因为这样的一条边显然在T中具有更优解,即使S变化改变了T,也改变不了有边比它优,它毫无意义的事实。
那么,删掉这些边~
同时,从kruskal的角度,考虑T中的边。
可以发现,T中至少有一个端点位于S的补集中的所有边一定会出现在最后的最小生成树中。
因为,S集合无论怎么乱变,带来的后果只是加入或删除刚改变的这条边,并需要删除或加入一条边。原来使S的补集中的点加入最小生成树的边是不会因此改变的,即使这条边连接了S和S的补集也一样。
换句话说,对T中至少有一个端点位于S的补集中的边在最终结果中的的存在性完全不构成影响。
那么就可以考虑缩掉T上的这些不属于S集合的点了,因为它们已经被确定了~
缩成一个点就好~
于是,考虑分治询问,每次把与分治区间内修改的边相关的所有点看做S,递归下去,同步缩点即可~
#include<iostream>#include<map>#include<set>#include<vector>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0' || '9'<ch){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar(); return x;}const int N=20009;const int M=50009;const int Q=50009;struct query{ int u,w;}op[Q];struct edge{ int u,v,w,id; bool del,un; edge(){del=un=0;}};inline bool operator < (edge a,edge b){return a.w<b.w;}vector<edge> e;ll ans[Q];int n,m,q,fa[N];inline int find(int x){ if(fa[x]==x)return x; return fa[x]=find(fa[x]);}inline void reset(int siz){ for(int i=1;i<=siz;i++) fa[i]=i;} inline bool merge(int u,int v){ int fu=find(u),fv=find(v); if(fv==fu)return 0; fa[fv]=fu;return 1;}inline void solve(int l,int r,vector<edge> e,int siz,ll sum,int addl,int addr){ map<int,int> ha; int mid=l+r>>1,ei=e.size(); if(l==r)addr=r; for(int i=0;i<ei;i++)//get edges' original name ha[e[i].id]=i; for(int i=addl;i<=addr;i++)//preadd edge if(ha.count(op[i].u)) e[ha[op[i].u]].w=op[i].w; sort(e.begin(),e.end());//sort for MST if(l==r)//getans { reset(siz+9); for(int i=0;i<ei;i++) if(merge(e[i].u,e[i].v)) sum+=e[i].w; ans[l]=sum; return; } set<int> need; map<int,int> hath; reset(siz+9); for(int i=l;i<=r;i++)//get need edges need.insert(op[i].u); for(int i=0;i<ei;i++) if(!need.count(e[i].id) && !merge(e[i].u,e[i].v))//ignore need edges,use the rest to build MST e[i].del=1; reset(siz+9); for(int i=0;i<ei;i++) if(need.count(e[i].id))//ignore all edges which was in pointset S merge(e[i].u,e[i].v); for(int i=0;i<ei;i++) if(!need.count(e[i].id) && !e[i].del && merge(e[i].u,e[i].v))//calc edges which must be in MST e[i].un=1,sum+=e[i].w; reset(siz+9); for(int i=0;i<ei;i++)//merge points with edges which must be in MST to ignore them if(e[i].un) merge(e[i].u,e[i].v); int top=0; for(int i=1;i<=siz;i++)//get points which were not added into MST yet if(find(i)==i) hath[i]=++top; vector<edge> ne; for(int i=0;i<ei;i++) if(!e[i].un && !e[i].del)//ignore must-in and mustn't-in edges { edge tmp=e[i]; tmp.u=hath[find(e[i].u)]; tmp.v=hath[find(e[i].v)]; ne.push_back(tmp); } solve(l,mid,ne,top,sum,l,0); solve(mid+1,r,ne,top,sum,l,mid);//preadd l-mid optmize}int main(){ n=read();m=read();q=read(); for(int i=1;i<=m;i++) { edge t; t.u=read(); t.v=read(); t.w=read(); t.id=i; e.push_back(t); } for(int i=1;i<=q;i++) { op[i].u=read(); op[i].w=read(); } solve(1,q,e,n,0,1,0); for(int i=1;i<=q;i++) printf("%lld\n",ans[i]); return 0;}
- [BZOJ2001][HNOI2010]City城市建设-CDQ分治
- [动态MST] [CDQ分治] BZOJ2001: [Hnoi2010]City 城市建设
- bzoj2001【HNOI2010】City 城市建设
- bzoj2001 [Hnoi2010]City 城市建设
- bzoj2001: [Hnoi2010]City 城市建设
- 【BZOJ2001】[Hnoi2010]City 城市建设
- BZOJ-2001-city城市建设-HNOI2010-CDQ分治
- bzoj2001: [Hnoi2010]City 城市建设 wikioi2332
- 【HNOI2010】【BZOJ2001】City 城市建设2015.4.9编辑修改
- bzoj2001 [Hnoi2010]City 城市建设 动态最小生成树
- 【BZOJ】2001 [Hnoi2010]City 城市建设 cdq分治——动态最小生成树
- [动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设
- 2001: [Hnoi2010]City 城市建设
- 2001: [Hnoi2010]City 城市建设
- BZOJ 2001: [Hnoi2010]City 城市建设
- bzoj 2001 [Hnoi2010]City 城市建设
- bzoj 2001: [Hnoi2010]City 城市建设
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- 学设计模式要看懂UML类图才行
- java Hotspot 内存管理白皮书
- 【安全牛学习笔记】TCPDUMP-抓包、筛选、高级筛选、过程文档记录
- 关于换工作
- 第一个AndRoid程序,主要内容
- [BZOJ2001][HNOI2010]City城市建设-CDQ分治
- 07-storm
- [0] Hello World
- DescriptionResource Path Location Type web.xml is missing and <failOnMissingWebXml> is set to true
- 栈-----noip2011 选择客栈
- Kappa:比Lambda更好更灵活的实时处理架构
- Python中的lambda
- CCS中的GEL语言
- Android 事件分发机制源码攻略(二) —— ViewGroup篇