# [summary] Zhu Liu algorithm of minimum tree graph

### Preface

I found that I didn't write a blog when I was reviewing...

To fill in one..

#### Minimum Arborescence

It is the minimum spanning tree of digraph, which can reach all nodes from the root, and has the least edge weight.

### Zhu Liu algorithm

In a very violent way, each point selects the smallest one among the edges pointing to it (the root node is not selected).

Then add the edge weight of each point.

Then there may be a ring, shrink it to a point, and then change the edge weight

val '- = val indicates that if val' is selected later, val must be disconnected

Keep doing this until you can't find the ring once and then stop.

Complexity O(N * M)O(N*M)O(N * M)

#### Template problem

BZOJ4349

The first time is the minimum tree chart, and the second time and later attack, just use the minimum one.

```#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#define SF scanf
#define PF printf
#define INF 0x3FFFFFFF
#define MAXN 60
#define MAXM 2600
using namespace std;
struct Edge{
int u,v;
double val;
Edge() {}
Edge(int u1,int v1,double val1):u(u1),v(v1),val(val1) {}
}edge[MAXM];
int num[MAXN],pre[MAXN],id[MAXN],vis[MAXN];
double minv[MAXN],in[MAXN];
int rt,ncnt;
double solve(int n){
double res=0;
while(1){
for(int i=1;i<=n;i++)
in[i]=INF;
for(int i=1;i<=ncnt;i++){
int u=edge[i].u;
int v=edge[i].v;
double val=edge[i].val;
if(in[v]>val){
in[v]=val;
pre[v]=u;
}
}
int tot=0;
memset(id,0,sizeof id);
memset(vis,0,sizeof vis);
in[rt]=0;
for(int i=1;i<=n;i++){
res+=in[i];
int v=i;
while(vis[v]!=i&&id[v]==0&&v!=rt){
vis[v]=i;
v=pre[v];
}
if(v!=rt&&id[v]==0){
id[v]=++tot;
for(int u=pre[v];u!=v;u=pre[u])
id[u]=tot;
}
}
if(tot==0)
break;
for(int i=1;i<=n;i++)
if(id[i]==0)
id[i]=++tot;
int cnt1=0;
for(int i=1;i<=ncnt;i++){
int u=edge[i].u;
int v=edge[i].v;
double val=edge[i].val;
val-=in[v];
if(id[u]!=id[v])
edge[++cnt1]=Edge(id[u],id[v],val);
}
rt=id[rt];
n=tot;
ncnt=cnt1;
}
return res;
}
int main(){
int n,u,v,m;
double val;
SF("%d",&n);
n++;
rt=n;
for(int i=1;i<=n-1;i++){
SF("%lf%d",&val,&num[i]);
minv[i]=val;
edge[++ncnt]=Edge(rt,i,val);
}
SF("%d",&m);
for(int i=1;i<=m;i++){
SF("%d%d%lf",&u,&v,&val);
minv[v]=min(minv[v],val);
edge[++ncnt]=Edge(u,v,val);
}
double res=solve(n);
for(int i=1;i<n;i++)
res+=(num[i]-1)*minv[i];
PF("%.2lf",res);
}

```

Posted on Mon, 02 Dec 2019 01:29:56 -0500 by katarra