bzoj1977 次小生成树【最小生成树+倍增】
来源:互联网 发布:centos 设置dns 编辑:程序博客网 时间:2024/05/29 15:10
解题思路:
题目要求的是严格次小生成树。
先说说不严格次小生成树怎么做。
先求最小生成树。然后枚举每一条不最小生成树上的边(x,y,len),那么如果要把这条边压入树中,肯定要删除原树中的一条边。由于要使新树最小,所以删除的只能是原树中x到y路径上的最大边mx1,可以用倍增来求。那么新树大小即为totlen-mx1+len。对所有边进行该操作,取最小值就是答案。
那如何求严格次小呢?
其实还是一样的思路,再多找一个x到y路径上的严格次小边mx2,如果len>mx1,那么那么新树大小即为totlen-mx1+len;如果len==mx1,那那么那么新树大小即为totlen-mx2+len。最后还是取最小值。
时间复杂度为O(nlogn)。
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<queue>#define ll long longusing namespace std;int getint(){ int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f;}const int N=100005,M=300005;struct node{ int x,y,w; inline friend bool operator < (const node &a,const node &b) { return a.w<b.w; }}bian[M];int n,m;int id[N],fa[N][20],mx1[N][20],mx2[N][20],dep[N];int tot,first[N],nxt[N<<1],to[N<<1],w[N<<1];ll totlen,ans;bool chs[M];void add(int x,int y,int z){ nxt[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z;}int find(int x){ return id[x]==x?x:id[x]=find(id[x]);}void kruskal(){ for(int i=1;i<=n;i++)id[i]=i; sort(bian+1,bian+m+1); int cnt=0; for(int i=1;i<=m;i++) { int x=find(bian[i].x),y=find(bian[i].y); if(x!=y) { cnt++; totlen+=bian[i].w; chs[i]=true; add(bian[i].x,bian[i].y,bian[i].w); add(bian[i].y,bian[i].x,bian[i].w); id[y]=x; if(cnt==n-1)break; } }}void dfs(int u){ for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1]; for(int i=1;i<20;i++)mx1[u][i]=max(mx1[u][i-1],mx1[fa[u][i-1]][i-1]); for(int i=1;i<20;i++) { mx2[u][i]=max(mx2[u][i-1],mx2[fa[u][i-1]][i-1]); if(mx1[u][i-1]<mx1[fa[u][i-1]][i-1]&&mx2[u][i]<mx1[u][i-1]) mx2[u][i]=mx1[u][i-1]; if(mx1[u][i-1]>mx1[fa[u][i-1]][i-1]&&mx1[fa[u][i-1]][i-1]>mx2[u][i]) mx2[u][i]=mx1[fa[u][i-1]][i-1]; } for(int e=first[u];e;e=nxt[e]) { int v=to[e]; if(v==fa[u][0])continue; fa[v][0]=u;mx1[v][0]=w[e]; dep[v]=dep[u]+1; dfs(v); }}int Find(int x,int y,int len){ int Mx1=0,Mx2=0; if(dep[x]<dep[y])swap(x,y); int delta=dep[x]-dep[y]; for(int i=19;i>=0;i--) if(delta&(1<<i)) { if(Mx1>mx1[x][i]&&mx1[x][i]>Mx2)Mx2=mx1[x][i]; if(Mx1<mx1[x][i])Mx2=max(Mx1,mx2[x][i]),Mx1=mx1[x][i]; x=fa[x][i]; } if(x==y)return Mx1==len?Mx2:Mx1; for(int i=19;i>=0;i--) if(fa[x][i]!=fa[y][i]) { if(Mx1>mx1[x][i]&&mx1[x][i]>Mx2)Mx2=mx1[x][i]; if(Mx1<mx1[x][i])Mx2=max(Mx1,mx2[x][i]),Mx1=mx1[x][i]; x=fa[x][i]; if(Mx1>mx1[y][i]&&mx1[y][i]>Mx2)Mx2=mx1[y][i]; if(Mx1<mx1[y][i])Mx2=max(Mx1,mx2[y][i]),Mx1=mx1[y][i]; y=fa[y][i]; } if(Mx1>mx1[x][0]&&mx1[x][0]>Mx2)Mx2=mx1[x][0]; if(Mx1<mx1[x][0])Mx2=max(Mx1,mx2[x][0]),Mx1=mx1[x][0]; x=fa[x][0]; if(Mx1>mx1[y][0]&&mx1[y][0]>Mx2)Mx2=mx1[y][0]; if(Mx1<mx1[y][0])Mx2=max(Mx1,mx2[y][0]),Mx1=mx1[y][0]; y=fa[y][0]; return Mx1==len?Mx2:Mx1;}void solve(int e){ int x=bian[e].x,y=bian[e].y,len=bian[e].w; int tmp=Find(x,y,len); ans=min(ans,totlen-tmp+len);}int main(){ //freopen("lx.in","r",stdin); n=getint(),m=getint(); for(int i=1;i<=m;i++) { bian[i].x=getint(); bian[i].y=getint(); bian[i].w=getint(); } kruskal(); dfs(1); ans=1e18; for(int i=1;i<=m;i++) if(!chs[i])solve(i); printf("%lld",ans);}
阅读全文
0 0
- bzoj1977 次小生成树【最小生成树+倍增】
- 【bzoj1977】【次小生成树】【树上倍增】
- bzoj1977 严格的次小生成树(LCA倍增)
- bzoj1977: [BeiJing2010组队]次小生成树 Tree 树上倍增
- bzoj1977 [BeiJing2010组队]次小生成树 倍增
- bzoj1977 [BeiJing2010组队]次小生成树 Tree (lca+倍增)
- bzoj1977 [BeiJing2010]次小生成树 Tree(kruskal+树上倍增)
- [BZOJ1977]严格次小生成树-kruskal+倍增维护
- bzoj1977: [BeiJing2010]次小生成树 kruskal+倍增LCA
- bzoj1977次小生成树
- 【BZOJ1977】【BJOI2011】严格次小生成树
- BZOJ1977 (严格)次小生成树
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree Kruskal+倍增LCA
- 【bzoj1977】【严格次小生成树】倍增维护链上最大次大值
- 【BJOI2010】次小生成树-最小生成树+倍增LCA
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- 无人机与民航客机之间的安全距离在哪里?
- 用一个晚上的时间告诉你:做手机OPPO也是认真的
- 宋仲基vivo X7自拍照遭曝光 Moonlight柔光灯效果太惊人
- mysql查询出所有重复的记录
- leetcode 204
- bzoj1977 次小生成树【最小生成树+倍增】
- 删除idea不编译class文件的位置
- Spring Boot——开发新一代Spring Java应用
- ABB副总裁顾纯元:柔性自动化怎么帮助制造业的转型升级?
- 详情:微软 262 亿美元收购 LinkedIn,后者将保持独立
- 【金融量化】我以为我是食物链顶层的收割者,想不到只是别人手中的镰刀
- linux系统中cut的用法
- <tarjan||拓扑>codevs 2066 三角恋
- Python 模拟知乎登陆,保存登陆cookie