https://vjudge.net/contest/311526#problem/G
General idea: given n(50) attributes, each attribute has a[i](500) level, a n d there are M(2000) courses. To participate in j course, c attribute should reach D.
In this way, you can upgrade your e attribute to f, and spend g yuan at the same time. Ask how much it costs to upgrade the attribute to full
Analysis: at the first sight of this problem, I felt like a kind of network flow, so I started to write it. Fortunately, the next door xmk big guy's prompt "you can try the network.
Flow, and then it starts to shut itself off. This is called the minimum tree graph. "So I started to write the minimum tree graph, but isn't the minimum tree graph that all points must be accessible?
But this question can make attribute I reach a[i], but it doesn't have to go through a[i]-1, so I began to get confused, feeling like I had a NP hard problem.
Later, I couldn't start to search the blog. I saw that there was a[i]-j - > a[i]-j-1 operation in other people's mapping methods. It seemed that it was also an epiphany to let the low attribute point by.
High attribute point arrival not only solves the conflict that the minimum tree graph needs to finish the point flow, but also solves the problem that level 5 cannot learn level 4.
It's too dish.
Finally, I will give you a code, which can be used as a template for you.
/////////////////////////////////////////Info///////////////////////////////////////////////// //Problem: //Date: //Skill: //Bug: /////////////////////////////////////////Definations///////////////////////////////////////////////// //Cycle control #define CLR(a) memset((a),0,sizeof(a)) #define F(i,a,b) for(int i=a;i<=int(b);++i) #define F2(i,a,b) for(int i=a;i>=int(b);--i) #define RE(i,n) for(int i=0;i<int(n);i++) #define RE2(i,n) for(int i=1;i<=int(n);i++) //Simplified percussion #define PII pair<int,int> #define PDD pair<double,double> #define PLL pair<long long ,long long> #define PB push_back #define MODY(n) (n%=mod)<0?n+=mod:n #define MODED(n) ((n)<0?(n)%mod+mod:(n)%mod) #define x first #define y second using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const long long llinf = 0x3f3f3f3f3f3f3f3f; ////////////////////////////////////////Options////////////////////////////////////////////////////// #define stdcpph #define CPP_IO #ifdef stdcpph #include<bits/stdc++.h> #else #include<ctype.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<algorithm> #include<functional> #ifdef CPP_IO #include<iostream> #include<iomanip> #include<string> #else #include<stdio.h> #endif #endif ////////////////////////////////////////Basic Functions////////////////////////////////////////////// template<typename INint> inline void IN(INint &x) { x = 0; int f = 1; char c; cin.get(c); while (c<'0' || c>'9') { if (c == '-')f = -1; cin.get(c); } while (c >= '0'&&c <= '9') { x = x * 10 + c - '0'; cin.get(c); } x *= f; } template<typename INint> inline void OUT(INint x) { if (x > 9)OUT(x / 10); cout.put(x % 10 + '0'); } ////////////////////////////////////////Added Functions////////////////////////////////////////////// const int maxn = int(30000); const int maxe = int(40000); int N, M; int a[maxn]; int c[maxn], L1[maxn], d[maxn], L2[maxn], money[maxn]; int cor[55][550],nid(0); int eid(0); struct Edge { int f, t, v; bool operator<(Edge ri)const { return v < ri.v; } }es[maxe], pre[maxn]; int root=1, cnt, id[maxn]; bool instk[maxn], vis[maxn]; void dfs(int u) { if (u == root) return; instk[u] = vis[u] = 1; if (!vis[pre[u].f])dfs(pre[u].f); else if (instk[pre[u].f]) { id[u] = ++cnt; for (int j = pre[u].f; j != u; j = pre[j].f)id[j] = cnt; } instk[u] = 0; if (!id[u]) id[u] = ++cnt; } //tn vertices and tm edges are stored as [1,n] in es and pre. int solve(int tn, int tm,int setroot) { root = setroot; int ans = 0; while (1) { for (int i = 1; i <= tn; ++i) pre[i].v = inf; for (int i = 1; i <= tm; ++i)pre[es[i].t] = min(pre[es[i].t], es[i]); memset(id + 1, 0, tn << 2), memset(vis + 1, 0, tn), id[root] = cnt = 1; for (int i = 1; i <= tn; ++i) if (i != root) { if (pre[i].v == inf)return -1; else ans += pre[i].v; if (!vis[i]) dfs(i); } if (cnt == tn) break; int mm = 0; for (int i = 1; i <= tm; ++i)if (id[es[i].f] != id[es[i].t]) es[++mm] = { id[es[i].f],id[es[i].t],es[i].v - pre[es[i].t].v }; tm = mm, tn = cnt, root = id[root]; } return ans; } ////////////////////////////////////////////Code///////////////////////////////////////////////////// int main() { //freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin); int T(1), cas(0); #ifdef CPP_IO// CPP_IO ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); //cin >> T; #else //IN(T); #endif ///////////////////////////////////////////////////////////////////////////////////////////////// while (++cas, T--,cin>>N>>M,N||M) { nid = eid = 0; F(i, 1, N)cin >> a[i]; F(i, 1, M) { cin >> c[i] >> L1[i] >> d[i] >> L2[i]>>money[i]; } F(i, 1, N)cor[i][0] = nid = 1; F(i, 1, N) { F(j, 1, a[i]) { cor[i][j] = ++nid; } } F(i, 1, N) { F(j, 1, a[i]) { es[++eid] = { cor[i][j],cor[i][j - 1],0 }; } } F(i, 1, M) { es[++eid] = { cor[c[i]][L1[i]],cor[d[i]][L2[i]],money[i] }; } int ans = solve(nid, eid,1); cout << ans << endl; } /////////////////////////////////////////////////////////////////////////////////////////////////// return 0; } //What to Debug /* -1.It's better to X all warning s, otherwise: https://vjudge.net/solution/19887176 0.See if you may need to read fast, endl 1.Array out of bounds, burst int, floating-point precision (check whether the precision meets the requirements of the topic, see whether there is floating-point comparison: eps), modulo operation, initialization of array, edge data, output format (cas) 2.Read through the code without logic error 3.Read the question and find the wrong meaning or algorithm 4.give up */