建出二分图,然后跑费用流就行了。。。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 305; const int maxm = 400005; const int INF = 0x3f3f3f3f; struct Edge { int v, c, w, next; Edge () {} Edge(int v, int c, int w, int next) : v(v), c(c), w(w), next(next) {} }E[maxm]; queue<int> q; int H[maxn], cntE; int cap[maxn]; int vis[maxn]; int dis[maxn]; int cur[maxn]; int flow, cost, s, t, T; void addedges(int u, int v, int c, int w) { E[cntE] = Edge(v, c, w, H[u]); H[u] = cntE++; E[cntE] = Edge(u, 0, -w, H[v]); H[v] = cntE++; } bool spfa() { memset(dis, INF, sizeof dis); cur[s] = -1; vis[s] = ++T; cap[s] = INF; dis[s] = 0; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = T - 1; for(int e = H[u]; ~e; e = E[e].next) { int v = E[e].v, c = E[e].c, w = E[e].w; if(c && dis[v] > dis[u] + w) { dis[v] = dis[u] + w; cap[v] = min(cap[u], c); cur[v] = e; if(vis[v] != T) { vis[v] = T; q.push(v); } } } } if(dis[t] >= 0) return false; cost += cap[t] * dis[t]; flow += cap[t]; for(int e = cur[t]; ~e; e = cur[E[e ^ 1].v]) { E[e].c -= cap[t]; E[e ^ 1].c += cap[t]; } return true; } int mfmc() { flow = cost = 0; while(spfa()); return cost; } void init() { cntE = T = 0; memset(H, -1, sizeof H); memset(vis, 0, sizeof vis); } struct node { int level, tuner, atk; }p[maxn]; int g[maxn][maxn]; int n, m; void work() { scanf("%d%d", &n, &m); s = 0, t = n + 1; int res = 0; for(int i = 1; i <= n; i++) { scanf("%d%d%d", &p[i].tuner, &p[i].level, &p[i].atk); res += p[i].atk; if(p[i].tuner) addedges(i, t, 1, 0); else addedges(s, i, 1, 0); } memset(g, 0, sizeof g); for(int kk = 1; kk <= m; kk++) { int level, atk, r; scanf("%d%d%d", &level, &atk, &r); if(r == 0) { for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(p[i].tuner == 0 && p[j].tuner == 1 && p[i].level + p[j].level == level) { int t2 = atk - p[i].atk - p[j].atk; if(t2 > 0) g[i][j] = max(g[i][j], t2); } } if(r == 1) { int tt; scanf("%d", &tt); if(p[tt].tuner == 0) { for(int i = 1; i <= n; i++) if(p[i].tuner == 1 && p[tt].level + p[i].level == level) { int t2 = atk - p[i].atk - p[tt].atk; if(t2 > 0) g[tt][i] = max(g[tt][i], t2); } } else { for(int i = 1; i <= n; i++) if(p[i].tuner == 0 && p[tt].level + p[i].level == level) { int t2 = atk - p[i].atk - p[tt].atk; if(t2 > 0) g[i][tt] = max(g[i][tt], t2); } } } if(r == 2) { int t1, t2; scanf("%d%d", &t1, &t2); if(p[t1].tuner == 0) { int tt = atk - p[t1].atk - p[t2].atk; if(tt > 0) g[t1][t2] = max(g[t1][t2], tt); } else { int tt = atk - p[t1].atk - p[t2].atk; if(tt > 0) g[t2][t1] = max(g[t2][t1], tt); } } } for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(g[i][j]) addedges(i, j, 1, -g[i][j]); printf("%d\n", res - mfmc()); } int main() { int _; scanf("%d", &_); while(_--) { init(); work(); } return 0; }