Preface
I found that I didn't write a blog when I was reviewing...
To fill in one..
Minimum ArborescenceIt 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 problemBZOJ4349
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); }