1. 程式人生 > >洛谷 P4180 【模板】嚴格次小生成樹[BJWC2010]【次小生成樹】

洛谷 P4180 【模板】嚴格次小生成樹[BJWC2010]【次小生成樹】

UC 註意 max code clu print etc using ios

嚴格次小生成樹模板
算法流程:
先用克魯斯卡爾求最小生成樹,然後給這個最小生成樹樹剖一下,維護邊權轉點權,維護最大值和嚴格次大值。
然後枚舉沒有被選入最小生成樹的邊,在最小生成樹上查一下這條邊的兩端點的路徑上的最長邊,如果最長邊等於枚舉到的邊的邊權,那麽選次長邊(沒有次長邊的話直接跳過),然後在最小生成樹的權值上減去路徑上最/次長邊,加上當前枚舉的邊的邊權
因為如果加入枚舉的邊的,那麽就形成了一個環,需要斷開一條邊
註意一開始單點次小值賦為0

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std; const int N=300005; int n,m,h[N],cnt,f[N],con,fa[N],si[N],hs[N],de[N],fr[N],id[N],rl[N],va[N],tmp; long long ans=1e18,sum; bool mk[N]; 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; }

洛谷 P4180 【模板】嚴格次小生成樹[BJWC2010]【次小生成樹】