n个项目,m个技术,每个项目可以赚取x[i]元,每个技术需要花费y[i]元,完成每个项目有一定的技术要求,也就是说某些技术必须先完成才能去完成这个项目,而且技术相互之间也有要求的,某些技术必须先完成才能去完成其他的技术。
显然的一点是可以看出来是最大权闭合问题,但是文中说的i必须先去j完成该怎么见图呢,开始我也建错了,样例都过不了,后来才仔细画了个图。
n=1,m=2;
x[1] = 10,y[1] = 4,y[2] = 5;
项目1需要技术1先完成,技术2也需要技术1完成。
主要是技术之间怎么建边。这里建成两种图(技术1->技术2 or 技术2->技术1),算下就知道了。
/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 1010; struct Edge{ int from, to, cap, flow; Edge(){} Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){} }; struct ISAP{ int p[maxn], num[maxn], cur[maxn], d[maxn]; int s, t, n, m; bool vis[maxn]; vector<int> G[maxn]; vector<Edge> edges; void init(int n) { this->n = n; for (int i = 0;i <= n;++i) { G[i].clear(); d[i] = INF; } edges.clear(); } void addedge(int from,int to,int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); m = (int)edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } bool bfs() { memset(vis, false,sizeof vis); queue<int> que; d[t] = 0; vis[t] = true; que.push(t); while(!que.empty()) { int u = que.front(); que.pop(); for (int i = 0;i < G[u].size();++i) { Edge& e = edges[G[u][i]^1]; if (e.cap > e.flow && !vis[e.from]) { vis[e.from] = true; d[e.from] = d[u] + 1; que.push(e.from); } } } return vis[s]; } int Augment() { int u = t, flow = INF; while(u != s) { Edge& e = edges[p[u]]; flow = min(flow, e.cap - e.flow); u = edges[p[u]].from; } u = t; while(u != s) { edges[p[u]].flow += flow; edges[p[u]^1].flow -= flow; u = edges[p[u]].from; } return flow; } int MaxFlow(int s,int t) { this->s = s,this->t = t; int ret = 0; bfs(); if (d[s] >= n) return 0; memset(num, 0,sizeof num); memset(cur, 0,sizeof cur); for (int i = 0;i < n;++i) { if (d[i] < INF) num[d[i]]++; } int u = s; while(d[s] < n) { if (u == t) { ret += Augment(); u = s; } bool ok = false; for (int i = cur[u];i < G[u].size();++i) { Edge& e = edges[G[u][i]]; if (e.cap > e.flow && d[u] == d[e.to] + 1) { ok = true; p[e.to] = G[u][i]; cur[u] = i; u = e.to; break; } } if (!ok) { int Min = n - 1; for (int i = 0;i < G[u].size();++i) { Edge& e = edges[G[u][i]]; if (e.cap > e.flow) Min = min(Min, d[e.to]); } if (--num[d[u]] == 0) break; num[d[u] = Min + 1]++; cur[u] = 0; if (u != s) u = edges[p[u]].from; } } return ret; } }isap; int tmp[51][51]; int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int icase = 0; int tt; scanf("%d",&tt); while(tt--) { int sum = 0; int n, m; scanf("%d%d",&n,&m); int s = 0, t = n+m+1; isap.init(t); int c; for (int i = 1;i <= n;++i){ scanf("%d",&c); isap.addedge(s, i, c); sum += c; }//cout << "sum = " << sum << endl; for (int j = 1;j <= m;++j) { scanf("%d",&c); isap.addedge(j+n, t, c); } int k; int u, v; for (int i = 1;i <= n;++i) { scanf("%d",&k); while(k--) { scanf("%d",&u); isap.addedge(i, u+1+n, INF); } } for (int i = 1;i <= m;++i) { for (int j = 1;j <= m;++j) { scanf("%d",&c); if (c == 1) isap.addedge(i+n,j+n,INF); } } printf("Case #%d: ", ++icase); printf("%d\n", sum - isap.MaxFlow(s, t)); } return 0; }