A few days ago, I learned the zhu liu algorithm of the minimum tree structure, instead of having a special understanding. I prepared a template to meet my needs. I couldn't think of a minimal tree structure that I could not find, I didn't see it, but I didn't understand the algorithm very well. I wrote it in a template and then it went through. --0
When I heard that it was the smallest tree structure, I suddenly realized that it was very bare, but later I thought it was not very bare. In fact, the key is to think about the edge that needs to be added back, paste a code--0
#pragma warning(disable:4996)#include<cstdio>#include<set>#include<cstring>#include<iostream>#include<stdlib.h>#include<vector>#include<map>#include<algorithm>#include<queue>#include<cmath>#include<functional>#include<string>using namespace std;#define maxn 550int n, m;int a[55];struct Edge{int u, v, w;Edge(int ui, int vi, int wi) :u(ui), v(vi), w(wi){}Edge(){}};vector<Edge> E;vector<int> vid[55];int in[maxn]; // minimum pre edge weightint pre[maxn]; // pre vertexint vis[maxn]; // vis arrayint id[maxn]; // mark down the idint nv; // nv is the number of vertex after shrinkingint directed_mst(int root,int vertex_num){int ret = 0; int nv = vertex_num;while (1){for (int i = 0; i < nv; ++i) in[i] = 1e9;for (int i = 0; i < E.size(); ++i){int u = E[i].u, v = E[i].v;if (E[i].w < in[v] && u != v){in[v] = E[i].w;pre[v] = u;}}for (int i = 0; i < nv; ++i){if (i == root) continue;if (in[i]>1e8) return -1;}int cnt = 0;memset(id, -1, sizeof(id));memset(vis, -1, sizeof(vis));in[root] = 0;for (int i = 0; i < nv; ++i){ret += in[i];int v = i;while (vis[v] != i&&id[v] == -1 && v != root){vis[v] = i;v = pre[v];}// v!=root means we find a circle,id[v]==-1 guarantee that it‘s not shrinked.if (v != root&&id[v] == -1){for (int u = pre[v]; u != v; u = pre[u]){id[u] = cnt;}id[v] = cnt++;}}if (cnt == 0) break;for (int i = 0; i < nv; ++i){if (id[i] == -1) id[i] = cnt++;}// change the cost of edge for each (u,v,w)->(u,v,w-in[v])for (int i = 0; i < E.size(); ++i){int v = E[i].v;E[i].u = id[E[i].u];E[i].v = id[E[i].v];if (E[i].u != E[i].v) E[i].w -= in[v];}// mark down the new rootroot = id[root];// mark down the new vertex numbernv = cnt;}return ret;}int main(){while (cin >> n >> m){if (n == 0 && m == 0) break;int tot = 0;for (int i = 1; i <= n; ++i) {vid[i].clear();scanf("%d", a + i);for (int j = 0; j <= a[i]; ++j){vid[i].push_back(++tot);}}++tot;E.clear();for (int i = 1; i <= n; ++i){for (int j = 0; j < vid[i].size(); ++j){for (int k = j + 1; k < vid[i].size(); ++k){E.push_back(Edge(vid[i][k], vid[i][j], 0));}}}int ci, l1, di, l2, wi;for (int i = 0; i < m; ++i){scanf("%d%d%d%d%d", &ci, &l1, &di, &l2, &wi);E.push_back(Edge(vid[ci][l1], vid[di][l2], wi));}for (int i = 1; i <= n; ++i){E.push_back(Edge(0, vid[i][0], 0));}int ans = directed_mst(0,tot);printf("%d\n", ans);}return 0;}