P4180 嚴格次小生成樹 BJWC2010

2022-03-17 23:21:11 字數 2091 閱讀 6089

題目鏈結

當時在暑假早就講了這道題了,只不過我現在才做了這道題。

題解:

我們要求次小生成樹的話,考慮先把最小生成樹求出來,因為如果我們用求最小生成樹的話,邊早已經從大到小排序好了,所以次小生成樹的就是替換最小生成樹上的一條邊所得。

那麼考慮如何來替換那一條邊,要保證嚴格次小,那麼我們需要替換掉最小生成樹上兩點間最大的邊權,這樣暴力列舉刪邊肯定是不行的,所以我們需要維護在最小生成樹上的邊。考慮用樹鏈剖分來維護(其實就是打不來倍增)

然而維護的時候我們不僅要維護邊權的最大值,還不能忘了再維護乙個邊權的次大值,因為最大值的邊權有可能與我們列舉的非樹邊相等,不滿足嚴格次小,所以還要維護次大值。

那麼這道題的解法就很容易了,列舉非樹邊,然後用非樹邊替換求出次小生成樹即可。時間複雜度nlogn+kruskal複雜度。

**如下:

#includeusing

namespace

std;

const

int maxn=1e6+7

;const

long

long inf=1e15;

struct

nodetree[maxn*4

];bool

cmp(node a,node b)

struct

ddedge[maxn*3

];struct

sbseg[maxn*4

];int

n,m,x,y,v;

intfa[maxn];

intget(int

x)int

head[maxn],cnt;

void add(int x,int y,int

v)long

long

ans;

void

kruskal()

}for(int i=1;i<=m;i++)

}}int

w[maxn],dep[maxn],siz[maxn],faa[maxn],son[maxn];

void dfs1(int x,int

f) }

}int top[maxn],id[maxn],va[maxn],in

;void dfs2(int x,int

topf)

}void pushup(int

now)

if(seg[now<<1].mx11|1

].mx1)

if(seg[now<<1].mx1==seg[now<<1|1

].mx1)

}void build(int now,int l,int

r)

int mid=(l+r)>>1

; build(now

<<1

,l,mid);

build(now

<<1|1,mid+1

,r);

pushup(now);

}pair

getmax(pair x,pairy)

if(x.first

if(x.first==y.first)

return

make_pair(ans1,ans2);

}pair

query(int now,int l,int

r)pair

link(int x,int

y)

if(dep[x]

res=getmax(res,query(1,id[y]+1

,id[x]));

return

res;

}void

solve()

else

if(tree[i].val>ass.second)}}

printf(

"%lld\n

",final);

}int

main()

view code

洛谷p4180嚴格次小生成樹

題意 求嚴格的次小生成樹 嚴格次小生成樹 value e 表示邊e的權值 e e m value e s value e em為最小生成樹邊集,es為次小生成樹邊集 就是次小生成樹邊權和一定要小於最小生成樹,而非嚴格的就不一定,也可能等於。非嚴格次小生成樹求法 是在最小生成樹邊集外 找到一條邊 假設...

P4180 BJWC2010 嚴格次小生成樹

題目 最小生成樹都會吧?不會的戳這裡 接下來我們用lca求每一條非樹邊在樹上環的最大邊權和次大邊權,然後求乙個min s mx v,s mx2 v,mn 就可以了,注意如果mx v,第一項不比較.code include include include include include include...

嚴格次小生成樹

顧名思義。生成樹,邊權和嚴格小於最小生成樹 一定和最小生成樹有關係。實際上,有 結論1 嚴格次小生成樹只在最小生成樹上改動一條邊 證明 改動一條邊有意義的話,必然改完這條邊,總和變大。那麼這至少是嚴格次小生成樹的最大值。再改一條也沒有意義。結論2 改動的那條邊w,一定是新加入的那條邊覆蓋的樹鏈的最大...