1.先求出最小生成樹
2.列舉不在最小生成樹上的每一條邊,加入最小生成樹構成環
3.每個環上找到原來最小生成樹上的最長的邊和次長的邊
4.如果最長的邊小於新加的邊,將最長邊去掉,否則去掉次長的邊,如果次長的邊等於最長的邊,不存在嚴格次小生成樹.
5.求權值
非嚴格次小生成樹只需要找到原來最小生成樹上的最長的邊去掉即可,允許出現結果權值與最小生成樹相同.
#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
const int n=2e5+10,m=3e5+10;
const ll inf=1e18;
int con=1,h[n],nex[2*m],to[2*m],par[n][17],lg[n],vis[n],p[n],s[m],use[m];
ll w[2*m],d[n],max1[n][32],max2[n][32];
struct edge
};vectore;
void add(int x,int y,ll z)
ll find(int x)
bool cmp(int x,int y)
else if(a1==c1)
else
}queueq;
void bfs(int x,int deep)
for(int i=h[x];i;i=nex[i])
}}void lca(int x,int y,ll &h1,ll &k1)
if(x==y)
for(int i=lg[d[x]];i>=0;--i)
}calmax1max2(m1,m2,max1[x][0],max2[x][0],m1,m2);
calmax1max2(m3,m4,max1[y][0],max2[y][0],m3,m4);
calmax1max2(m1,m2,m3,m4,h1,k1);
}int main()
for(int i=0;i<=n;++i)
p[i]=i;
for(int i=0;i<(int)e.size();++i)
s[i]=i;
int tmp=e.size();
sort(s,s+tmp,cmp);
ll ans=kruskal();
for(int i=2;i<=n;++i)
lg[i]=(i&(i-1))==0?lg[i-1]+1:lg[i-1];
vis[1]=1;
bfs(1,0);
ll se=1e16;
for(int i=0;i<(int)e.size();++i)
cout
}
最小生成樹 次小生成樹
一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...
次小生成樹
演算法引入 設g v,e,w 是連通的無向圖,t是圖g的一棵最小生成樹 如果有另一棵樹t1,滿足不存在樹t t t1 則稱t1是圖g的次小生成樹 演算法思想 鄰集的概念 由t進行一次可行交換得到的新的生成樹所組成的集合,稱為樹t的鄰集,記為n t 設t是圖g的最小生成樹,如果t1滿足 t1 min,...
次小生成樹
分類 圖論 2013 02 12 15 03 32人閱讀收藏 舉報次小生成樹 在求最小生成樹時,用陣列path i j 來表示mst中i到j最大邊權。求完後,直接列舉所有不在mst中的邊,把它加入到mst中構成一棵新的樹,且該樹有環,此環是由剛加入的邊 i,j 造成的,所以可以通過刪除path i ...