BZOJ1977: [BeiJing2010组队]次小生成树 Tree
来源:互联网 发布:龙珠激斗刷龙石软件 编辑:程序博客网 时间:2024/06/07 05:44
题目链接
严格次小生成树模板题。构建最小生成树后,枚举每一条非树边,找两顶点链间的最大边,若最大边和当前边边权向同,则找次大边,更新答案。
【代码】
#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 100005#define M 200005#define INF 1000000001using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f;}ll ans;int n,m,cnt,mn=INF,mx1,mx2;int father[N];bool flag[300005];int b[M],p[N],nextedge[M],w[M];int deep[N],d1[N][17],d2[N][17],fa[N][17];class Edge{ public: int x,y,z;}e[300005];void Add(int x,int y,int z){ cnt++; b[cnt]=y; nextedge[cnt]=p[x]; p[x]=cnt; w[cnt]=z;}void Anode(int x,int y,int z){ Add(x,y,z);Add(y,x,z);}bool cmp(Edge a,Edge b){ return a.z<b.z;}void Input_Init(){ n=read();m=read(); for(int i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].z=read(); sort(e+1,e+1+m,cmp);}int findf(int x){ return father[x]==x?x:father[x]=findf(father[x]);}void Kruskal(){ int tot=0; for(int i=1;i<=n;i++) father[i]=i; for(int i=1;i<=m;i++) { int fx=findf(e[i].x),fy=findf(e[i].y); if(fx!=fy) { father[fx]=fy;tot++;flag[i]=1; ans+=e[i].z;Anode(e[i].x,e[i].y,e[i].z); if(tot==n-1) break; } }}void dfs(int x,int f){ for(int i=1;i<=16;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]); if(d1[x][i-1]==d1[fa[x][i-1]][i-1]) d2[x][i]=max(d2[x][i-1],d2[fa[x][i-1]][i-1]); else { d2[x][i]=min(d1[x][i-1],d1[fa[x][i-1]][i-1]); d2[x][i]=max(d2[x][i],d2[x][i-1]); d2[x][i]=max(d2[x][i],d2[fa[x][i-1]][i-1]); } } for(int i=p[x];i;i=nextedge[i]) { int v=b[i]; if(v==f) continue; fa[v][0]=x; d1[v][0]=w[i]; deep[v]=deep[x]+1; dfs(v,x); }}void Update(int x,int i){ if(d1[x][i]>mx1) { mx2=mx1; mx1=d1[x][i]; } mx2=max(mx2,d2[x][i]);}void Work(int a){ mx1=0,mx2=0; int x=e[a].x,y=e[a].y,z=e[a].z; if(deep[x]<deep[y]) swap(x,y); int t=deep[x]-deep[y]; for(int i=0;i<16;i++) { if((1<<i)&t) { Update(x,i); x=fa[x][i]; } } for(int i=16;i>=0;i--) { if(fa[x][i]!=fa[y][i]) { Update(x,i); x=fa[x][i]; Update(y,i); y=fa[y][i]; } } if(x!=y) { if(d1[x][0]>mx1) { mx2=mx1; mx1=d1[x][0]; } else if(d1[x][0]>mx2) mx2=d1[x][0]; if(d1[y][0]>mx1) { mx2=mx1; mx1=d1[y][0]; } else if(d1[y][0]>mx2) mx2=d1[y][0]; } if(mx1!=z) mn=min(mn,z-mx1); else mn=min(mn,z-mx2);}void Solve(){ for(int i=1;i<=m;i++) { if(flag[i]) continue; Work(i); } printf("%lld\n",ans+mn);}int main(){ Input_Init(); Kruskal(); dfs(1,0); Solve(); return 0;}
0 0
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977 [BeiJing2010组队]次小生成树 Tree
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree 树上倍增
- bzoj1977 [BeiJing2010组队]次小生成树 Tree (lca+倍增)
- BZOJ1977 [BeiJing2010组队] [次小生成树 Tree]
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree【次小生成树】【LCA】
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- bzoj1977 [BeiJing2010组队]次小生成树 倍增
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree Kruskal+倍增LCA
- [BZOJ1977][BeiJing2010组队]次小生成树 Tree(kruskal+链剖)
- 【BZOJ1977】【MST】【LCA】[BeiJing2010组队]次小生成树 Tree 题解
- bzoj1977 [BeiJing2010]次小生成树 Tree(kruskal+树上倍增)
- 【BZOJ 1977】 [BeiJing2010组队]次小生成树 Tree
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree
- 1977: [BeiJing2010组队]次小生成树 Tree kruskal+倍增
- 搜集一些喜欢的文字
- ios NSAssert()
- 信号量与PV操作
- (AIDL)Android Interface definition language
- 类的组合
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- Eclipse中添加Python插件
- 辉哥写的ajax装载table
- Java NIO 2:缓冲区
- 防止SpringMVC注解方式的XSS攻击的方法
- PHP桶排序算法
- Java多线程 ReentrantReadWriteLock深入分析
- Python学习-2:基本数据类型
- java开发中常见问题