題目鏈結
當時在暑假早就講了這道題了,只不過我現在才做了這道題。
題解:
我們要求次小生成樹的話,考慮先把最小生成樹求出來,因為如果我們用求最小生成樹的話,邊早已經從大到小排序好了,所以次小生成樹的就是替換最小生成樹上的一條邊所得。
那麼考慮如何來替換那一條邊,要保證嚴格次小,那麼我們需要替換掉最小生成樹上兩點間最大的邊權,這樣暴力列舉刪邊肯定是不行的,所以我們需要維護在最小生成樹上的邊。考慮用樹鏈剖分來維護(其實就是打不來倍增)
然而維護的時候我們不僅要維護邊權的最大值,還不能忘了再維護乙個邊權的次大值,因為最大值的邊權有可能與我們列舉的非樹邊相等,不滿足嚴格次小,所以還要維護次大值。
那麼這道題的解法就很容易了,列舉非樹邊,然後用非樹邊替換求出次小生成樹即可。時間複雜度nlogn+kruskal複雜度。
**如下:
#includeusingview codenamespace
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()
洛谷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,一定是新加入的那條邊覆蓋的樹鏈的最大...