最小樹形圖(朱劉演算法)
洛谷P4716 【模板】最小樹形圖
題意:
n個點m條邊得有向圖,以s為根的最小樹形圖,及除s外其他點的入度為1
#include<bits/stdc++.h>
#define N 103
#define M 10002
#define INF 210000001
#define LL long long
using namespace std;
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
struct EDGE{
int a,b,v;
}w[M];
int minn[N],id[N],vis[N],fa[N];
int cnt=0;
//cnt當前圖環的數量
//id[u]代表u節點在第id[u]個環中
//vis[u]打標記避免一直走環
//minn[u]為當前連到u點的最短邊的邊權 fa[v]當前連到v點的最短邊的u
LL ans=0;
int zhuliu(int n,int m,int r)
{
while(1)
{
for(int i=1;i<=n;++i) minn[i]=INF,id[i]=vis[i]=0;
for(int i=1;i<=m;++i)
{
if(w[i].a!=w[i].b&&w[i].v<minn[w[i].b])//不是自環 並且邊權比選定的還小
fa[w[i].b]=w[i].a,minn[w[i].b]=w[i].v;
}
int u;
minn[r]=0;
for(int i=1;i<=n;++i)
{
if(minn[i]==INF)return 0;//存在一個不可以連線的點,什麼不能找到最小樹形圖
ans+=minn[i];//這裡就會更新到ans中
for(u=i;u!=r&&!id[u]&&vis[u]!=i;u=fa[u])vis[u]=i;//打上標記,這裡走過的是一條鏈,vis打上i而不是1,因為可能多條邊指向一個點
if(u!=r&&!id[u])//沒有走到根,找到一個新環
{
id[u]=++cnt;
for(int v=fa[u];v!=u;v=fa[v])id[v]=cnt;
}
}
if(!cnt)return 1;//沒有環了,說明現在就是最小樹形圖,邊權和在上面就已經加入ans了
for(int i=1;i<=n;++i)
if(!id[i])id[i]=++cnt;//i節點不存在當前樹中 就給他自己成一個環
for(int i=1;i<=m;++i)
{
int last=minn[w[i].b];//last等於當前連進v點的邊的最小權值
if((w[i].a=id[w[i].a])!=(w[i].b=id[w[i].b]))w[i].v-=last;
//縮環的時候記得加入答案,環上的出邊直接接上,入邊要注意,選一條入邊相當於刪掉一條環邊
//當前邊的兩個端點不在同一個環內
}
n=cnt;cnt=0;r=id[r];//縮完點後 當前點數就為環數 根節點就是根節點所在的環
}
}
int main()
{
int n=read(),m=read(),r=read();
for(int i=1;i<=m;++i)
w[i].a=read(),w[i].b=read(),w[i].v=read();
if(zhuliu(n,m,r))printf("%lld\n",ans);
else printf("-1\n");
}
相關文章
- 最小樹形圖(有向圖的最小生成樹)朱劉演算法演算法
- poj 3164 Command Network(最小樹形圖模板題)朱_ 劉演算法演算法
- 演算法-圖論-最小生成樹演算法圖論
- 圖論中的最小生成樹演算法圖論演算法
- 演算法 最小高度樹演算法
- 【圖論】最小生成樹圖論
- 圖論 最小生成樹圖論
- 【JAVA演算法】圖論演算法 --求最小生成樹Prim演算法Java演算法圖論
- 最小生成樹__Kurskal演算法演算法
- 最小生成樹__Prim演算法演算法
- 最小生成樹的演算法演算法
- Kruskal 最小生成樹演算法演算法
- Prim 最小生成樹 圖解圖解
- 最小生成樹之 Prim 演算法演算法
- 【演算法學習】最小生成樹演算法
- 演算法與資料結構之帶權圖與圖最小生成樹演算法資料結構
- C語言圖形設計 劉振安pdfC語言
- 最小生成樹——Prim演算法和Kruscal演算法演算法
- 最小生成樹:Kruskal演算法和Prim演算法演算法
- 最小生成樹-Prim演算法和Kruskal演算法演算法
- 演算法學習之路|最小生成樹——prime演算法演算法
- 最小生成樹之Prim演算法和Kruskal演算法演算法
- 最小生成樹prim普里姆演算法演算法
- 最小生成樹之普里姆演算法演算法
- Boruvka求最小生成樹(菠蘿演算法)演算法
- 圖論之帶權圖「最小生成樹之Prim」圖論
- 前端必會演算法 - 最小生成樹問題前端演算法
- 最小生成樹(MinSpanTree)的Kruskal演算法演算法
- 東哥帶你刷圖論第五期:Kruskal 最小生成樹演算法圖論演算法
- 最小生成樹
- 圖論之帶權圖「最小生成樹(Minimum Span Tree)」圖論
- 圖論之帶權圖「最小生成樹prim的優化」圖論優化
- 如何在 Java 中實現最小生成樹演算法Java演算法
- 圖形演算法視覺化演算法視覺化
- 圖論之帶權圖「最小生成樹prim的最佳化」圖論
- 最小斯坦納樹初探
- 最小度限制生成樹
- 【模板】最小生成樹