int in[N], pre[N];//in[i]记录每轮i点入边中最小的边权,pre[i]记录最小边权对应的端点编号int vst[N], scc[N];intZhuliu(){int ans =0;while(1){for(int i =1; i <= n; i++)
in[i]= INF;// 初始化for(int i =1; i <= m; i++){int u = edge[i].from, v = edge[i].to;if(u != v && edge[i].val < in[v])// 遍历所有边,对每个点找到最小的入边
in[v]= edge[i].val, pre[v]= u;}for(int i =1; i <= n; i++)// 判定无解if(i != root && in[i]== INF)//有一个点找不到入边了return-1;int sc =0;for(int i =1; i <= n; i++)
vst[i]= scc[i]=0;for(int i =1; i <= n; i++){if(i == root)continue;
ans += in[i];int v = i;while(vst[v]!= i &&!scc[v]&& v != root)// 找环,找回自己/找到一个缩过点的/找到根节点了都退出{
vst[v]= i;
v = pre[v];}if(!scc[v]&& v != root)//一定是找回自己{
scc[v]=++sc;// 缩点for(int u = pre[v]; u != v; u = pre[u])
scc[u]= sc;}}if(sc ==0)break;// 无环,得到解for(int i =1; i <= n; i++)if(!scc[i])
scc[i]=++sc;for(int i =1; i <= m; i++)//重构图{int u = edge[i].from, v = edge[i].to;
edge[i].from = scc[u], edge[i].to = scc[v];if(scc[u]!= scc[v])
edge[i].val -= in[v];// 修改边权}
root = scc[root];
n = sc;}return ans;}