[模板] 最小树形图/朱刘算法

最小树形图

图的 (叶向) 树形图指的是从一个点出发, 能到达其他所有节点, 且基图是一棵树的子图.

求图的最小树形图常用朱刘算法, 时间复杂度 (O(nm)).

一个例子:

代码

const int nsz=105,msz=1e4+50,ninf=1e9;

struct te{int f,t,v;}e0[msz];
int np,ne,rt;
int in[nsz],pre[nsz],id[nsz],vi[nsz];
//叶向树形图 
ll zhu_liu(){
	ll res=0;
	while(1){
		int cnt=0;
		rep(i,1,np)in[i]=ninf,pre[i]=id[i]=vi[i]=0;
		rep(i,1,ne){
			int f=e0[i].f,t=e0[i].t,v=e0[i].v;
			if(f!=t&&in[t]>v)in[t]=v,pre[t]=f;
		}
		in[rt]=0;
		rep(i,1,np){
			if(in[i]==ninf)return -1;
			res+=in[i];
			int u;
			for(u=i;u!=rt&&id[u]==0&&vi[u]!=i;u=pre[u])vi[u]=i;
			if(vi[u]==i){
				id[u]=++cnt;
				for(int v=pre[u];v!=u;v=pre[v])
				id[v]=cnt;
			}
		}
		if(cnt==0)return res;
		rep(i,1,np)if(id[i]==0)id[i]=++cnt;
		rep(i,1,ne){
			te &e=e0[i];
			int tmp=in[e.t];
			e.f=id[e.f],e.t=id[e.t];
			if(e.f!=e.t)e.v-=tmp;
		}
		np=cnt;
		rt=id[rt];
	}
}
原文地址:https://www.cnblogs.com/ubospica/p/11079560.html