完全动态最小生成树(sgu529,HNOI2010city)
2014-01-07 15:18
211 查看
对于加边和删边改变成无穷大就好了。
话说HN好喜欢考裸的比较偏的模板题。会就会,不会考场很难想出来吧。
思想很好理解,就是对询问分治,然后缩点递归。和AHOI2013有道题比较类似。
具体实现可以看英文论文和GYZ在WC上讲课的PPT。
网上的代码都是nlog^2 n的,于是我就去写了nlogn的,结果编程能力太弱。
导致代码太丑,常数巨大.实际运行效果不明显。
而且说是完全动态,但是对于动态维护MST,以及维护路径路径问题
分治貌似莫法搞(WC2006),好像只能写动态树
话说HN好喜欢考裸的比较偏的模板题。会就会,不会考场很难想出来吧。
思想很好理解,就是对询问分治,然后缩点递归。和AHOI2013有道题比较类似。
具体实现可以看英文论文和GYZ在WC上讲课的PPT。
网上的代码都是nlog^2 n的,于是我就去写了nlogn的,结果编程能力太弱。
导致代码太丑,常数巨大.实际运行效果不明显。
而且说是完全动态,但是对于动态维护MST,以及维护路径路径问题
分治貌似莫法搞(WC2006),好像只能写动态树
#include<cstdio> #include<cstring> #include<algorithm> #define N 200010 using namespace std; struct Que {int k,d;}h ; struct Num {int a,b;}num ; struct Ege {int a,b,c,w;}Eg ,eg[20] ,neg[20] ,nEg ; int falg,n,m,q,use ,have ,tot[20],t1,t2[20],f ; bool cmp(Ege a,Ege b) { return a.c<b.c; } int find(int v) { if (f[v]==v) return f[v]; f[v]=find(f[v]); return f[v]; } void YES(int t) { for (int i=1;i<=m;i++) { f[eg[t][i].a]=eg[t][i].a; f[eg[t][i].b]=eg[t][i].b; } for (int i=1;i<=m;i++) if (use[eg[t][i].w]==1) f[find(eg[t][i].a)]=find(eg[t][i].b); for (int i=1;i<=m;i++) if (use[eg[t][i].w]!=1&&find(eg[t][i].a)!=find(eg[t][i].b)) { use[eg[t][i].w]=2; f[find(eg[t][i].a)]=find(eg[t][i].b); } } void No(int t) { for (int i=1;i<=m;i++) { have[eg[t][i].a]=have[eg[t][i].b]=0; f[eg[t][i].a]=eg[t][i].a; f[eg[t][i].b]=eg[t][i].b; } int n=0; for (int i=1;i<=m;i++) { if (have[eg[t][i].a]==0) {n++;have[eg[t][i].a]=1;} if (have[eg[t][i].b]==0) {n++;have[eg[t][i].b]=1;} } int tot=0,k=m; for (int i=1;i<=m;i++) if (use[eg[t][i].w]!=1) { if (f[find(eg[t][i].a)]!=find(eg[t][i].b)) { f[find(eg[t][i].a)]=find(eg[t][i].b); tot++; if (n-1==tot) {k=i;break;} } else use[eg[t][i].w]=3; } for (int i=k+1;i<=m;i++) if (!use[eg[t][i].w]) use[eg[t][i].w]=3; } int kru(int k,int d,int t) { if (tot[t]==1) return d; if (eg[t][1].w==k) eg[t][1].c=d; else eg[t][2].c=d; if (eg[t][1].c<eg[t][2].c) return eg[t][1].c; return eg[t][2].c; } void hebin(int t,int m1) { int l1=1,l2=1,m2=t1; for (int i=1;i<=m1;i++) { use[eg[t][i].w]=0; num[eg[t][i].w].a=eg[t][i].a; num[eg[t][i].w].b=eg[t][i].b; } for (int i=1;i<=m2;i++) use[Eg[i].w]=1; for (int i=1;i<=m1;i++) { while (l1<=m1&&use[eg[t][l1].w])l1++; if (l1>m1||(l2<=m2&&Eg[l2].c<eg[t][l1].c)) nEg[i]=Eg[l2++]; else nEg[i]=eg[t][l1++]; } for (int i=1;i<=m1;i++) { eg[t][i]=nEg[i]; eg[t][i].a=num[eg[t][i].w].a; eg[t][i].b=num[eg[t][i].w].b; } } void deal(int l,int r,int t,long long sum) { m=tot[t]; for (int i=1;i<=m;i++) use[eg[t][i].w]=0; for (int i=l;i<=r;i++) use[h[i].k]=1; YES(t);No(t); falg=0; for (int i=1;i<=m;i++) { f[eg[t][i].a]=eg[t][i].a; f[eg[t][i].b]=eg[t][i].b; } int &nm=tot[t+1]; nm=0; for (int i=1;i<=m;i++) if (use[eg[t][i].w]==2) { f[find(eg[t][i].a)]=find(eg[t][i].b); sum+=eg[t][i].c; } for (int i=1;i<=m;i++) if (use[eg[t][i].w]==0||use[eg[t][i].w]==1&&find(eg[t][i].a)!=find(eg[t][i].b)) { ++nm; eg[t+1][nm].a=find(eg[t][i].a); eg[t+1][nm].b=find(eg[t][i].b); eg[t+1][nm].c=eg[t][i].c; eg[t+1][nm].w=eg[t][i].w; } if (l==r) { printf("%I64d\n",sum+kru(h[l].k,h[l].d,t+1)); t1=1; Eg[t1].c=h[l].d;Eg[t1].w=h[l].k; return ; } int mid=(l+r)/2; deal(l,mid,t+1,sum); t2[t]=t1; for (int i=1;i<=t1;i++) neg[t][i]=Eg[i]; hebin(t+1,nm); t1=0; deal(mid+1,r,t+1,sum); int l1=1,l2=1,t3=0; for (int i=1;i<=t2[t];i++) use[neg[t][i].w]=0; for (int i=1;i<=t1;i++) use[Eg[i].w]=1; while (l1<=t1||l2<=t2[t]) { while (l2<=t2[t]&&use[neg[t][l2].w])l2++; if (l1>t1&&l2>t2[t]) break; if (l2>t2[t]||(l1<=t1&&Eg[l1].c<neg[t][l2].c)) nEg[++t3]=Eg[l1++]; else nEg[++t3]=neg[t][l2++]; } t1=t3; for (int i=1;i<=t1;i++) Eg[i]=nEg[i]; } int main() { scanf("%d%d%d",&n,&m,&q); for (int i=1;i<=m;i++) { scanf("%d%d%d",&Eg[i].a,&Eg[i].b,&Eg[i].c); Eg[i].w=i; } for (int i=1;i<=q;i++) scanf("%d%d",&h[i].k,&h[i].d); sort(Eg+1,Eg+1+m,cmp); tot[0]=m; for(int i=1;i<=m;i++) eg[0][i]=Eg[i]; deal(1,q,0,0); return 0; }
相关文章推荐
- sgu529. It's Time to Repair the Roads 简化版动态最小生成树
- SGU 323 Aviamachinations 最小生成树变形
- BZOJ1050 HAOI2006旅行(最小生成树+动态树)
- 51Nod 1601 完全图的最小生成树计数
- 51Nod1601 完全图的最小生成树计数
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- ☆ [WC2006] 水管局长 「LCT动态维护最小生成树」
- 【BZOJ】2001 [Hnoi2010]City 城市建设 cdq分治——动态最小生成树
- 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
- 51nod 算法马拉松22 完全图的最小生成树计数 【Trie树+图论】
- 51nod 1601 完全图的最小生成树计数 Trie+kruskal
- 51nod 1601 完全图的最小生成树计数 字典树+最小生成树
- ☆ [NOI2014] 魔法森林 「LCT动态维护最小生成树」
- [动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设
- [分治][Trie][prufer数列] 51Nod 1601 完全图的最小生成树计数
- 并查集+Kruscal最小生成树; 温习了一下并查集, 同时又对静态数组的动态使用体会了一下;.
- 想完全使用代码动态生成GridView真难
- HDU 5483 Nux Walpurgis 图的最小生成树中必要的边的数目 动态MST问题
- poj 1258 Agri-Net 最小生成树 prim算法+heap不完全优化 难度:0
- 【UVa】11354 Bond 最小生成树,动态LCA,倍增思想