日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(luogu4180) [Beijing2010组队]次小生成树Tree

發布時間:2024/8/26 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (luogu4180) [Beijing2010组队]次小生成树Tree 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

嚴格次小生成樹

首先看看如果不嚴格我們怎么辦。

非嚴格次小生成樹怎么做

由此,我們發現一個結論,求非嚴格次小生成樹,只需要先用kruskal算法求得最小生成樹,然后暴力枚舉非樹邊,替換路徑最大邊即可。

那要是嚴格呢?

我們發現如果是嚴格的次小生成樹,那么將一條邊替換另一條時,這兩條邊的權值一定不相同

但是,我們知道,替換邊肯定大于等于被替換邊(因為如果替換邊小于被替換邊,就存在一顆包含替換邊而不包含被替換邊的一棵權值更小的生成樹,原樹就不是最小生成樹了)

所以替換邊要么等于路徑上最大的邊,要么比最大的邊還大。

利用這個性質,我們只需要維護路徑中的最大值和次大值,當替換邊等于路徑上的最大值,我們直接換用嚴格次大值即可。

一些細節

1.我維護兩點之間路徑最大值用的是LCT,但是正解是LCA。LCT必須要開O2才能跑過去。

2.數組要開足夠大,最后統計答案時要開long long,不然會爆int

我的代碼

#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <queue> #define rg register int #define ll long long #define RG register #define il inline using namespace std;il ll gi() {RG ll x=0;rg o=0;RG char ch=getchar();while(ch!='-'&&(ch<'0'||'9'<ch)) ch=getchar();if(ch=='-') o=1,ch=getchar();while('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();return o?-x:x; } int n,m; #define SZ 7000010struct Edge {int a,b;ll w;}e[SZ]; bool cmp(Edge a,Edge b) {return a.w<b.w;}#define lson tr[x].ch[0] #define rson tr[x].ch[1] struct Splaytree{int fa,ch[2],rev,mxp,mxp2;}tr[SZ]; il void pushup(rg x) {tr[x].mxp=x; tr[x].mxp2=0;if(e[tr[lson].mxp].w>e[tr[x].mxp].w) tr[x].mxp=tr[lson].mxp;if(e[tr[rson].mxp].w>e[tr[x].mxp].w) tr[x].mxp=tr[rson].mxp;// 維護 最大if(e[tr[lson].mxp].w!=e[tr[x].mxp].w && (e[tr[lson].mxp].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[lson].mxp;if(e[tr[lson].mxp2].w!=e[tr[x].mxp].w && (e[tr[lson].mxp2].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[lson].mxp2; if(e[tr[rson].mxp].w!=e[tr[x].mxp].w && (e[tr[rson].mxp].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[rson].mxp;if(e[tr[rson].mxp2].w!=e[tr[x].mxp].w && (e[tr[rson].mxp2].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[rson].mxp2; // 維護嚴格次大 } il void pushdown(rg x) {if(tr[x].rev){tr[lson].rev^=1,tr[rson].rev^=1;swap(lson,rson),tr[x].rev=0;} } il bool isroot(rg x) {return tr[tr[x].fa].ch[0]!=x && tr[tr[x].fa].ch[1]!=x; } il void rotate(rg x) {rg y=tr[x].fa,z=tr[y].fa;rg k=tr[y].ch[1]==x;if(!isroot(y)) tr[z].ch[y==tr[z].ch[1]]=x;tr[x].fa=z;tr[y].ch[k]=tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa=y;tr[x].ch[k^1]=y,tr[y].fa=x;pushup(y),pushup(x); } int stk[SZ],top; il void splay(rg x) {stk[top=1]=x;for(rg i=x;!isroot(i);i=tr[i].fa) stk[++top]=tr[i].fa;for(;top;--top) pushdown(stk[top]);while(!isroot(x)){rg y=tr[x].fa,z=tr[y].fa;if(!isroot(y))(tr[y].ch[0]==x)^(tr[z].ch[0]==y)?rotate(x):rotate(y);rotate(x);} } il void access(rg x) {for(rg y=0;x;y=x,x=tr[x].fa)splay(x),rson=y,pushup(x);} il void makeroot(rg x) {access(x);splay(x);tr[x].rev^=1;} il int findroot(rg x) {access(x);splay(x);while(lson) x=lson;return x;} il void split(rg x,rg y) {makeroot(x);access(y);splay(y);} il int query(rg x,rg y) {split(x,y);return tr[y].mxp;} //求x 到 y最大值 il int query2(rg x,rg y) {split(x,y);return tr[y].mxp2;} // 求x 到 y嚴格次大值 il void link(rg x,rg y) {makeroot(x);tr[x].fa=y;} il void cut(rg x,rg y) {split(x,y);if(tr[y].ch[0]==x)tr[y].ch[0]=tr[x].fa=0;} int fa[SZ];int find_fa(rg x) {if(x!=fa[x]) fa[x]=find_fa(fa[x]);return fa[x];} //一行并查集 bool check[SZ];int main() {n=gi(),m=gi();for(rg i=1;i<=m;++i) e[i]=(Edge){gi(),gi(),gi()};// 先求一遍最小生成樹 ans 記錄最小生成樹邊的大小RG ll ans=0;sort(e+1,e+1+m,cmp); for(rg i=1;i<=n;++i) fa[i]=i; // 初始化并查集for(rg f1,f2,i=1;i<=m;++i){f1=find_fa(e[i].a);f2=find_fa(e[i].b);if(f1!=f2){check[i]=1; // check=1 表示最小生成樹中有這一條邊 反之fa[f1]=f2;ans+=e[i].w;link(e[i].a+m,i);link(e[i].b+m,i);}}#define INF 2147483647 #define Getmin(a,b) (a)=(a)>(b)?(b):(a) RG ll Ans=INF;for(rg f1,f2,i=1;i<=m;++i){if(check[i]) continue; //我們選擇不再最小生成樹上的邊rg mxp=query(e[i].a+m,e[i].b+m);if(e[mxp].w==e[i].w){rg mxp2=query2(e[i].a+m,e[i].b+m);if(!mxp2 || e[mxp2].w==e[mxp].w) continue;Getmin(Ans,e[i].w-e[mxp2].w);}else Getmin(Ans,e[i].w-e[mxp].w);}cout<<ans+Ans;return 0; }

轉載于:https://www.cnblogs.com/tply/p/8423955.html

總結

以上是生活随笔為你收集整理的(luogu4180) [Beijing2010组队]次小生成树Tree的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。