【BZOJ】1977 [BeiJing2010组队]次小生成树 Tree kruskal+LCA
来源:互联网 发布:mac os x 10.13 镜像 编辑:程序博客网 时间:2024/05/16 06:55
题目传送门
这题好像在好久以前就讲过啊……为什么我现在才去做……
其实正解挺好想的,首先做一棵最小生成树,然后枚举一条非树边,显然这条非树边的加入可以使原本树上的唯一路径形成一个环,把这个环上严格第二小的边删掉,就是一棵严格次小生成树了。然后对所有的次小生成树求一个最小权值即可。
至于怎么查找原来的唯一路径上的严格次大值,可以用ST表维护最大值和次大值。
附上AC代码:
#include <cstdio>#include <cctype>#include <algorithm>using namespace std;typedef long long ll;const int M=3e5+10,N=1e5+10;struct note{ int x,y,w; bool operator < (const note lyf) const {return w<lyf.w;}}a[M];struct side{ int to,w,nt;}s[N<<1];int n,m,fa[N],h[N],num,d[N],f[N][20],mx1[N][20],mx2[N][20],mn;ll ans;bool b[M];inline char nc(void){ static char ch[100010],*p1=ch,*p2=ch; return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;}inline void read(int &a){ static char c=nc();int f=1; for (;!isdigit(c);c=nc()) if (c=='-') f=-1; for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc()); return (void)(a*=f);}inline int gf(int x){return x==fa[x]?x:fa[x]=gf(fa[x]);}inline void add(int x,int y,int w){ s[++num]=(side){y,w,h[x]},h[x]=num; s[++num]=(side){x,w,h[y]},h[y]=num;}inline void so(int x,int fa){ for (int i=1; i<=17; ++i){ if (d[x]<(1<<i)) break; f[x][i]=f[f[x][i-1]][i-1]; mx1[x][i]=max(mx1[x][i-1],mx1[f[x][i-1]][i-1]); if (mx1[x][i-1]==mx1[f[x][i-1]][i-1]) mx2[x][i]=max(mx2[x][i-1],mx2[f[x][i-1]][i-1]); else { mx2[x][i]=min(mx1[x][i-1],mx1[f[x][i-1]][i-1]); mx2[x][i]=max(mx2[x][i],max(mx2[x][i-1],mx2[f[x][i-1]][i-1])); } } for (int i=h[x]; i; i=s[i].nt) if (s[i].to!=fa) d[s[i].to]=d[f[s[i].to][0]=x]+1,mx1[s[i].to][0]=s[i].w,so(s[i].to,x);}inline int lca(int x,int y){ if (d[x]<d[y]) swap(x,y);int t=d[x]-d[y]; for (int i=0; i<=17; ++i) if (t&(1<<i)) x=f[x][i]; for (int i=17; i>=0; --i) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; if (x==y) return x; return f[x][0];}inline void calc(int x,int fa,int w){ int d1=0,d2=0,t=d[x]-d[fa]; for (int i=0; i<=17; ++i) if (t&(1<<i)){ if (mx1[x][i]>d1) d2=d1,d1=mx1[x][i]; d2=max(d2,mx2[x][i]),x=f[x][i]; } if (d1!=w) mn=min(mn,w-d1); else mn=min(mn,w-d2); return;}int main(void){ read(n),read(m); for (int i=1; i<=m; ++i) read(a[i].x),read(a[i].y),read(a[i].w); sort(a+1,a+1+m); for (int i=1; i<=n; ++i) fa[i]=i; for (int i=1; i<=m; ++i){ int fx=gf(a[i].x),fy=gf(a[i].y); if (fx!=fy) fa[fx]=fy,ans+=a[i].w,b[i]=1,add(a[i].x,a[i].y,a[i].w); } so(1,0),mn=2e9; for (int i=1; i<=m; ++i) if (!b[i]){ int t=lca(a[i].x,a[i].y); calc(a[i].x,t,a[i].w),calc(a[i].y,t,a[i].w); } return printf("%lld\n",ans+mn),0;}
阅读全文
0 0
- 【BZOJ】1977 [BeiJing2010组队]次小生成树 Tree kruskal+LCA
- 1977: [BeiJing2010组队]次小生成树 Tree kruskal+倍增
- BZOJ - 1977 [BeiJing2010组队]次小生成树 Tree Kruskal演算法+最近公共祖先
- BZOJ 1977([BeiJing2010组队]次小生成树 Tree-LCA的位运算)
- 【BZOJ 1977】 [BeiJing2010组队]次小生成树 Tree
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree
- 【BZOJ 1977】[BeiJing2010组队]次小生成树 Tree
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree Kruskal+倍增LCA
- bzoj1977 [BeiJing2010组队]次小生成树 Tree (lca+倍增)
- bzoj 1977 [BeiJing2010组队]次小生成树 Tree [严格的次小生成树]
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree【次小生成树】【LCA】
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
- bzoj 1977: [BeiJing2010组队]次小生成树
- 1977: [BeiJing2010组队]次小生成树 Tree
- [BZOJ1977][BeiJing2010组队]次小生成树 Tree(kruskal+链剖)
- Linux基本命令
- GitHub-将本地仓库与远程仓库连接
- 收缩数据库
- Rpackage【dplyr】
- 作业
- 【BZOJ】1977 [BeiJing2010组队]次小生成树 Tree kruskal+LCA
- ThreadLocal简单测试
- Unity5.6 2D物理引擎Effector
- hdu1255覆盖的面积
- JVM异常解析
- 在head中定义样式的范例
- 在使用composer下载TP5的时候遇到 Your configuration does not allow connections to http://packagist.phpcomposer.
- MySQL 对于千万级的大表要怎么优化?
- 面向对象-接口特点