【BZOJ1977】[BeiJing2010组队]次小生成树 Tree Kruskal+倍增LCA
2014-10-04 15:18
597 查看
次小生成树:
先用Kruskal求出最小生成树(当然用Prim……也没关系~),再枚举未出现在最小生成树中的边加入到其中,则形成了一个环。求出环中除新加边外权值最大的边(使得新增权值最小)并删去,即得到次小生成树。
事实上,环路中权值最小的边就是新加入的边两端点间的路径上权值最小的边,此处可以用倍增LCA维护。另外由于需求出严格次小生成树,于是还要维护路径上边权的严格次小值。详见代码。
[BeiJing2010组队]次小生成树 C++代码实现:
先用Kruskal求出最小生成树(当然用Prim……也没关系~),再枚举未出现在最小生成树中的边加入到其中,则形成了一个环。求出环中除新加边外权值最大的边(使得新增权值最小)并删去,即得到次小生成树。
事实上,环路中权值最小的边就是新加入的边两端点间的路径上权值最小的边,此处可以用倍增LCA维护。另外由于需求出严格次小生成树,于是还要维护路径上边权的严格次小值。详见代码。
[BeiJing2010组队]次小生成树 C++代码实现:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define INF 0x7f7f7f7f #define N 100010 #define M 300010 int n,m; bool vis[M]; int cnt,f ,head ,to[N*2],next[N*2],val[N*2]; int deep ,fa [17],d1 [17],d2 [17],ans=INF; long long tot; struct data{int x,y,z;}a[M]; int find(int x) { return x==f[x]?x:f[x]=find(f[x]); } bool cmp(data x,data y) { return x.z<y.z; } void add(int x,int y,int z) { to[++cnt]=y; val[cnt]=z; next[cnt]=head[x]; head[x]=cnt; } void dfs(int x,int d) { for(int i=1;i<=16&&deep[x]<=(1<<i);i++) fa[x][i]=fa[fa[x][i-1]][i-1], d1[x][i]=max(d1[x][i-1],d1[fa[x][i-1]][i-1]), d2[x][i]=d1[x][i-1]==d1[fa[x][i-1]][i-1]? max(d2[x][i-1],d2[fa[x][i-1]][i-1]): max(max(d2[x][i-1],d2[fa[x][i-1]][i-1]),min(d1[x][i-1],d1[fa[x][i-1]][i-1])); deep[x]=d; for(int i=head[x];i;i=next[i]) if(to[i]!=fa[x][0]) fa[to[i]][0]=x, d1[to[i]][0]=val[i], dfs(to[i],d+1); } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); for(int i=16;i>=0;i--) if(deep[fa[x][i]]>=deep[y]) x=fa[x][i]; if(x==y) return x; int re; for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; else re=fa[x][i]; return re; } int getans(int x,int y,int z) { int t=lca(x,y),re1=0,re2=0; int dis1=deep[x]-deep[t],dis2=deep[y]-deep[t]; for(int i=16;i>=0;i--) { if(dis1&(1<<i)) { re2=re1==d1[x][i]?max(re2,d2[x][i]):max(min(re1,d1[x][i]),max(re2,d2[x][i])); re1=max(re1,d1[x][i]); x=fa[x][i]; } if(dis2&(1<<i)) { re2=re1==d1[y][i]?max(re2,d2[y][i]):max(min(re1,d1[y][i]),max(re2,d2[y][i])); re1=max(re1,d1[y][i]); y=fa[y][i]; } } return re1==z?z-re2:z-re1; } int main() { cin>>n>>m; for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); sort(a+1,a+m+1,cmp); for(int i=1;i<=n;i++) f[i]=i; for(int t=0,i=1;i<=m;i++) { int fx=find(a[i].x),fy=find(a[i].y); if(fx!=fy) { f[fx]=fy; vis[i]=true; add(a[i].x,a[i].y,a[i].z); add(a[i].y,a[i].x,a[i].z); tot+=a[i].z; if(++t==n-1) break; } } dfs(1,1); for(int i=1;i<=m;i++) if(!vis[i]) ans=min(ans,getans(a[i].x,a[i].y,a[i].z)); cout<<tot+ans; }
相关文章推荐
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree
- 【BZOJ 1977】[BeiJing2010组队]次小生成树 Tree
- BZOJ 1977([BeiJing2010组队]次小生成树 Tree-LCA的位运算)
- BZOJ - 1977 [BeiJing2010组队]次小生成树 Tree Kruskal演算法+最近公共祖先
- bzoj1977 [BeiJing2010组队]次小生成树 倍增
- 【BZOJ】1977 [BeiJing2010组队]次小生成树 Tree kruskal+LCA
- 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree
- bzoj1977 [BeiJing2010组队]次小生成树 Tree
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree【次小生成树】【LCA】
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
- [bzoj1977][BeiJing2010组队]次小生成树 Tree——树上倍增+lca
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree 最小生成树+倍增