洛谷 P4180 【模板】严格次小生成树[BJWC2010]【次小生成树】
2018-04-29 20:53
639 查看
严格次小生成树模板
算法流程:
先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值。
然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点的路径上的最长边,如果最长边等于枚举到的边的边权,那么选次长边(没有次长边的话直接跳过),然后在最小生成树的权值上减去路径上最/次长边,加上当前枚举的边的边权
因为如果加入枚举的边的,那么就形成了一个环,需要断开一条边
注意一开始单点次小值赋为0
#include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> using namespace std; const int N=300005; int n,m,h ,cnt,f ,con,fa ,si ,hs ,de ,fr ,id ,rl ,va ,tmp; long long ans=1e18,sum; bool mk ; struct qwe { int ne,to,va; }e[N<<1]; struct xds { int l,r,mx,cmx; }t[N<<1]; struct bian { int u,v,w; }a[N*3]; bool cmp(const bian &a,const bian &b) { return a.w<b.w; } int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } inline int zhao(int x) { return x==f[x]?x:f[x]=zhao(f[x]); } void add(int u,int v,int w) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; e[cnt].va=w; h[u]=cnt; } void dfs1(int u,int fat) { fa[u]=fat; de[u]=de[fat]+1; si[u]=1; for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fat) { va[e[i].to]=e[i].va; dfs1(e[i].to,u); si[u]+=si[e[i].to]; if(si[e[i].to]>si[hs[u]]) hs[u]=e[i].to; } } void dfs2(int u,int top) { fr[u]=top; id[u]=++tmp; rl[tmp]=u; if(!hs[u]) return; dfs2(hs[u],top); for(int i=h[u];i;i=e[i].ne) if(e[i].to!=hs[u]&&e[i].to!=fa[u]) dfs2(e[i].to,e[i].to); } void build(int ro,int l,int r) { t[ro].l=l,t[ro].r=r; if(l==r) { t[ro].mx=va[rl[l]]; return; } int mid=(l+r)>>1; build(ro<<1,l,mid); build(ro<<1|1,mid+1,r); t[ro].mx=max(t[ro<<1].mx,t[ro<<1|1].mx); if(t[ro<<1].mx==t[ro<<1|1].mx) t[ro].cmx=max(t[ro<<1].cmx,t[ro<<1|1].cmx); else t[ro].cmx=min(t[ro<<1].mx,t[ro<<1|1].mx); } int ques(int ro,int l,int r,int w) { if(t[ro].l==l&&t[ro].r==r) return t[ro].mx==w?t[ro].cmx:t[ro].mx; int mid=(t[ro].l+t[ro].r)>>1; if(r<=mid) return ques(ro<<1,l,r,w); else if(l>mid) return ques(ro<<1|1,l,r,w); else return max(ques(ro<<1,l,mid,w),ques(ro<<1|1,mid+1,r,w)); } int wen(int u,int v,int w) { int re=0; while(fr[u]!=fr[v]) { if(de[fr[u]]<de[fr[v]]) swap(u,v); re=max(re,ques(1,id[fr[u]],id[u],w)); u=fa[fr[u]]; } if(u!=v) { if(de[u]>de[v]) swap(u,v); re=max(re,ques(1,id[u]+1,id[v],w)); } return re; } int main() { n=read(),m=read(); for(int i=1;i<=m;i++) a[i].u=read(),a[i].v=read(),a[i].w=read(); sort(a+1,a+1+m,cmp); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m&&con<n-1;i++) { int fu=zhao(a[i].u),fv=zhao(a[i].v); if(fu!=fv) { f[fu]=fv,con++,sum+=a[i].w; add(a[i].u,a[i].v,a[i].w),add(a[i].v,a[i].u,a[i].w); mk[i]=1; } } dfs1(1,0); dfs2(1,1); build(1,1,n); for(int i=1;i<=m;i++) if(!mk[i]) ans=min(ans,sum-wen(a[i].u,a[i].v,a[i].w)+a[i].w); printf("%lld\n",ans); return 0; }
相关文章推荐
- 洛谷——P3366 【模板】最小生成树
- [洛谷3366]【模板】最小生成树
- 洛谷 P3366 【模板】最小生成树
- 洛谷P3366 【模板】最小生成树
- 洛谷——最小生成树模板
- 洛谷 P3366 【模板】最小生成树
- 洛谷 P3366 【模板】最小生成树
- 洛谷3366 最小生成树模板题
- 洛谷 [模板]最小生成树
- 最小生成树(模板)洛谷3366
- [BJWC2010] 严格次小生成树
- 洛谷P3366 【模板】最小生成树
- 洛谷 P3366 【模板】最小生成树
- P3366 最小生成树【模板】 洛谷
- HDU 1863 畅通工程(最小生成树模板题)
- 洛谷P3796 【模板】AC自动机(加强版)
- PHPWord利用模板替换字符串生成精确的word文档
- [CFF认证]201509-3模板生成系统(C++)
- [hoj 1632]Jungle Roads[Kruskal最小生成树模板题]
- Enterprise Architect 12 修改模板,适应mysql生成ddl