Regionals >> Asia-tehran >> 7530-cafebazaar
> Asia-tehran >> 7530-cafebazaar Best match minimum cost feasible flow ">
Topic Links: 7530
A company has n developers, there is a M app can be developed. Some of these developers must choose, some apps are required. Each developer is known to develop the benefits of each app to maximize revenue. (Each developer develops a maximum of one app, one per app at most)
Topic Ideas:
Solution 1:2 Graph Best match (km algorithm)
Add some virtual developers and virtual apps, non-essential apps can be developed by virtual developers, the revenue is 0, in turn, non-essential developers can develop virtual apps, the revenue is 0. Virtual developers can then also develop virtual apps, with a profit of 0, which allows the KM to meet the composition conditions.
Note: The necessary developers and their corresponding non-developer apps are set directly to a negative INF2 value, so that they have an edge between them but if you really want to choose this side, the final answer is definitely negative. That is, there is no viable solution. The necessary apps and their corresponding developers
setting of the weight value:
If (there is an important app) edge weights plus inf
if (there is an important developer) edge value plus inf
//up to two INF
Then you can apply the template.
Here's the code:
#include <iostream> #include <iomanip> #include <fstream> #include <sstream> #include <cmath > #include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #include < functional> #include <numeric> #include <string> #include <set> #include <map> #include < stack> #include <vector> #include <queue> #include <deque> #include <list> using namespace std
;
#define LL Long long #define MOD 1000000000 const int N = 105;
CONST LL INF = 100000000000000LL;
CONST LL INF2 = 1000000000000LL; int nx,ny;//the number of points on both sides of NX, number of first team, NY, second team.
Note that NX <= NY, otherwise it will die loop.
ll g[n][n];//Two-figure description G[i][j],i belongs to the first team, J belongs to the second team.
ll linker[n],lx[n],ly[n];//y points in the matching state, X, y points in the label LL Slack[n];
BOOL Visx[n],visy[n];
BOOL DFS (int x) {visx[x] = true;
for (int y = 0; y < ny; y++) {if (visy[y]) continue;
ll tmp = Lx[x] + ly[y]-g[x][y]; if (TMP = = 0) {Visy[y] = TruE if (linker[y] = =-1 | |
DFS (Linker[y])) {linker[y] = x;
return true;
}} else if (Slack[y] > tmp) slack[y] = tmp;
} return false;
} ll KM () {memset (LINKER,-1,SIZEOF (linker));
memset (ly,0,sizeof (ly));
for (int i = 0;i < nx;i++) {lx[i] =-inf;
for (int j = 0;j < ny;j++) if (G[i][j] > Lx[i]) lx[i] = G[i][j];
} for (int x = 0;x < nx;x++) {for (int i = 0;i < ny;i++) Slack[i] = INF;
while (true) {memset (visx,false,sizeof (VISX));
memset (visy,false,sizeof (Visy));
if (DFS (x)) break;
ll d = INF;
for (int i = 0;i < ny;i++) if (!visy[i] && d > slack[i]) d = slack[i];
for (int i = 0;i < nx;i++) if (Visx[i]) lx[i]-= D; for (int i = 0;i < ny;i++) {if (Visy[i]) ly[i] + = D;
else Slack[i]-= D;
}}} ll res = 0;
for (int i = 0;i < ny;i++) if (linker[i]! =-1) Res + = G[linker[i]][i];
return res;
} int imp[105];
int imb[105];
int main () {int n,m;
while (CIN >> n >> m) {if (n = = 0 && m = = 0) break;
memset (imp,0,sizeof (imp));
memset (imb,0,sizeof (IMB));
memset (G,0,sizeof (g));
NX = NY = max (n,m);
int t,x,a,b;
CIN >> T;
while (t--) {cin >> x;
IMP[X-1] = 1;
for (int i = 0; i < NX; i++) {g[x-1][i] =-inf2;
/* cannot be set to INF because the set to INF is no point connected, but set to INF2 (less than INF) indicates that the edge can be connected, if you must connect, even if it is negative, there is no answer */}}
CIN >> T;
while (t--) {cin >> x; IMB[X-1] = 1;
for (int i = 0; i < NX; i++) {g[i][x-1] =-inf2;
}} for (int i = 0; i < n; i++) {cin >> t;
while (t--) {cin >> a >> b;
G[i][a-1] = b;
if (Imp[i]) g[i][a-1] + = MOD;
if (Imb[a-1]) g[i][a-1] + = MOD;
}} ll ans = KM ();
if (ans < 0) cout <<-1 << Endl;
else cout << ans% MOD << Endl;
}}/* 2 4 1 1 1 3 2 1 8 2 10 3 2 2 3 10 4 50 4 3 3 1 2 4 2 1 3 1 1 200 2 2 700 3 200 2 2 300 3 100 1 1 500 */
Solution Two: Maximum cost feasible flow
Theory:
Concept distinction:
minimum cost maximum flow: first guarantee maximum flow, second cost minimum
cost feasible flow: Minimum guaranteed cost:
minimum cost maximum flow: Constantly find the shortest path to augment, until the augmented road is not found.
minimum cost feasible flow: continuously find the shortest path to augment until the shortest length found is positive or not found.
According to test instructions, this problem should be solved with a minimum cost, rather than the maximum flow of the minimum cost.
Fake a start and end point, as shown in the figure, the capacity is 1, if there is a required app or developer, this edge value is set to INF.
Build diagram:
* from S to all developers, the capacity is 1, if the key developer Benquan is +inf, otherwise it is 0.
* Developers to the development of the app edge, capacity is 1, edge is the development reward
* app to the meeting point edge, capacity is 1, if the key app Benquan is +inf, otherwise 0
Then apply the minimum cost flow template, because the maximum cost, the stored value is the edge of the right are negative.
> Asia-tehran >> 7530-cafebazaar Best match minimum cost feasible flow ">
Here's the code:
#include <iostream> #include <iomanip> #include <fstream> #include <sstream> #include <cmath > #include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #include < functional> #include <numeric> #include <string> #include <set> #include <map> #include < stack> #include <vector> #include <queue> #include <deque> #include <list> using namespace std
;
#define LL A long typedef, long flow_t;
typedef long Long cost_t;
const int MAXN = 10000;
const int MAXM = 100000;
Const flow_t INF = 1e9;
Const flow_t inf = 1E9;
struct Edge {int from, to, NX;
flow_t cap, Flow;
cost_t cost; Edge () {} edge (int _from, int _to, int _nx, flow_t _cap, cost_t _cost): From (_from), to (_to), NX (_NX), Cap (_CAP),
Flow (0), cost (_cost) {}} E[MAXM];
cost_t DIS[MAXN];
int G[MAXN], PRE[MAXN], VIS[MAXN]; int sz, N; s source point, t sink point void init (int n) {memset (G,-1, siZeof (g[0]) * n); SZ = 0;
n = n; } void Addedge (int u, int V, flow_t F, cost_t c)//u, v {e[sz] = Edge (U, V, G[u], F, +c);
G[u] = sz++; E[sz] = Edge (V, u, G[v], 0,-c);
G[V] = sz++;
} bool Extand (int S, int T) {std::queue<int> Q;
memset (Vis, 0, sizeof (vis[0)) * N);
memset (Pre,-1, sizeof (pre[0)) * N);
for (int i = 0; i < N; ++i) dis[i] = inf; Q.push (S); Vis[s] = 1;
Dis[s] = 0; while (!
Q.empty ()) {int u = q.front (); Q.pop ();
vis[u]=0;
for (int it = g[u]; ~it; it = e[it].nx) {int v = e[it].to; if (E[it].cap > E[it].flow && dis[v] > Dis[u] + e[it].cost) {Dis[v] = Dis[u] +
E[it].cost, pre[v] = it;
if (!vis[v]) Q.push (v), vis[v] = true; }}} return dis[t] <= 0; Change to Dis[t] <= 0 Find the feasible flow, change to dis[t] < inf for minimum cost Max stream} std::p air<flow_t, cost_t> solve (int S, int T) {flow_t max
Flow = 0; cost_t mincost = 0;
while (Extand (S, T)) {flow_t = inf;
for (int it = pre[t]; ~it; it = Pre[e[it].from]) {std::min (e[it].cap-e[it].flow);
} Mincost + = Dis[t], maxflow + =;
for (int it = pre[t]; ~it; it = Pre[e[it].from]) {E[it].flow + =, E[it ^ 1].flow-=;
}} return Std::make_pair (Maxflow, mincost);
} int imp[1005];
int imb[1005];
int main () {int n,m;
while (CIN >> n >> m) {if (n = = 0 && m = = 0) break;
memset (imp,0,sizeof (imp));
memset (imb,0,sizeof (IMB));
Init (n + m + 2);
0 for the virtual starting point int t1,t2,t,x,a,b;
CIN >> T;
T1 = t;
while (t--) {cin >> x;
IMP[X] = 1;
} for (int i = 1; I <= n; i++) {if (!imp[i]) Addedge (0,i,1,0);
else Addedge (0,i,1,-inf); }
CIN >> T;
t2 = t;
while (t--) {cin >> x;
Imb[x + n] = 1;
} for (int i = n + 1; i < n + m + 1; i++) {if (!imb[i]) Addedge (i,n + M + 1,1,0);
else Addedge (i,n + M + 1,1,-inf);
} for (int i = 1; I <= n; i++) {cin >> t;
while (t--) {cin >> a >> b;
Addedge (I,a + n,1,-b);
}} pair<flow_t, cost_t> ans = solve (0,1 + n + m);
Long Long tmp = (t1 + T2) * INF *-1;
if (Ans.second > tmp) cout <<-1 << Endl;
else cout << (Ans.second *-1)% INF << Endl;
} return 0; }