次小生成樹Tree

2022-03-19 22:38:26 字數 1570 閱讀 9392

小c最近學了很多最小生成樹的演算法,prim演算法、kurskal演算法、消圈演算法等等。正當小c洋洋得意之時,小p又來潑小c冷水了。小p說,讓小c求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也就是說:如果最小生成樹選擇的邊集是em,嚴格次小生成樹選擇的邊集是es,那麼需要滿足:(value(e)表示邊e的權值)

\[∑e∈emvalue(e)<∑e∈esvalue(e)

\]這下小 c 蒙了,他找到了你,希望你幫他解決這個問題。

第一行包含兩個整數n 和m,表示無向圖的點數與邊數。 接下來 m行,每行 3個數x y z 表示,點 x 和點y之間有一條邊,邊的權值為z。

包含一行,僅乙個數,表示嚴格次小生成樹的邊權和。(資料保證必定存在嚴格次小生成樹)

先kruscal最小生成樹,然後列舉非樹邊,權值為w,將邊的兩端點的路徑(lca)上的最長邊用w替換,但由於我們求的是嚴格次小生成樹,所以當最長邊邊權==w時,需要用嚴格次大邊替代,因此用倍增維護lca上的嚴格次大值和最大值.

具體見**注釋:

#define ll long long

#include#include#include#define rg register

using namespace std;

const int n=1e5+5,m=3e5+5;

inline ll read()

while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();

return x*w;

}inline ll min(ll a,ll b)

ll n,m,cnt,num,cost,ans=100000000000000;

ll last[n],par[n],dep[n],f[n][25],f1[n][25],f2[n][25];

//f[i][j]表示i節點2^j祖先的序號,f1[i][j]表示從i到f[i][j]路徑上的最大邊權,f1[i][j]表示嚴格次大邊權.

bool used[m];

struct edgee[2*m];

struct edgme1[m];

void insert(ll u,ll v,ll w)

;last[u]=cnt;

e[++cnt]=(edge);last[v]=cnt;

}bool cmp(edgm a,edgm b)

}if(a!=b)

dwq[++ct]=f1[a][0];

dwq[++ct]=f1[b][0];

dwq[++ct]=f2[a][0];

dwq[++ct]=f2[b][0];

}sort(dwq+1,dwq+ct+1);

for(ll i=ct;i>=1;i--)if(dwq[i]}int main()

; sort(e1+1,e1+m+1,cmp);

kruskal();

init();

for(ll i=1;i<=m;i++)

printf("%lld\n",ans);

return 0;

}

次小生成樹 Tree(倍增)

時間限制 1000 ms 記憶體限制 524288 kb 小 c 最近學了很多最小生成樹的演算法,prim 演算法 kurskal 演算法 消圈演算法等等。正當小 c 洋洋得意之時,小 p 又來潑小 c 冷水了。小 p 說,讓小 c 求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也...

HYSBZ 1977 次小生成樹 Tree

題意 給定乙個有 n 個點 m 條邊的無向帶權圖,求嚴格次小生成樹。n 1e5,m 3e5 解題思路 求非嚴格次小生成樹時,替換路徑上的最大邊,加入的邊權可能與其相等,故倍增時多維護乙個路徑上嚴格的次大值即可。include using namespace std typedef long long...

最小生成樹 Tree

參考資料 description 給你乙個無向帶權連通圖,每條邊是黑色或白色。讓你求一棵最小權的恰好有need條白色邊的生成樹。題目保證有解。input 第一行v,e,need分別表示點數,邊數和需要的白色邊數。接下來e行 每行s,t,c,col表示這邊的端點 點從0開始標號 邊權,顏色 0白色1黑...