Less Time, More profit
.
.
题目是挺裸的网络流,也算例题了吧
源点和商铺连一条流量为收益的边,汇点和工厂连一条流量为工厂投资的花费。因为最大流等于最小割,对于每一个商铺,要么把商铺利益割掉,要么把工厂花费割掉,最后的收益为所有商铺的收益减去最小割就是最大利润。对于时间,我是利用了二分保证最小。
.
.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>
#include <algorithm>
#include <string.h>
const int maxlongint=1 << 31 -1;
bool flag[500], all;
int i, j, k, n, m, tot, ans, s, t, sum, l;
int a[500001], b[500001], next[500001];
int last[505], x[505], y[505], r[505], w[505], count[505], cur[505], fa[505], dist[505], dat[505];
struct Node1 {
int pro;
int num;
int index[500];
}bb[500];
struct Node{
int pay, t, index;
bool operator<(Node &other) {
if (t <= other.t) return true;
return false;
}
}aa[500];
int insert(int x, int y, int z) {
tot++;
a[tot] = y;
b[tot] = z;
next[tot] = last[x];
last[x] = tot;
tot++;
a[tot] = x;
b[tot] = 0;
next[tot] = last[y];
last[y] = tot;
}
int min(int x, int y) {
if (x < y) return x ;
else return y;
}
int sap(int s, int t) {
int i, j, k, x, p, sum;
count[0] = 1;
count[1] = t-1;
for (i = 1; i <= t-1; i++) dist[i] = 1;
dist[t] = 0;
for (i = 1; i <= t; i++) {
cur[i] = last[i];
fa[i] = 0;
dat[i] = 0;
}
dat[s] = maxlongint;
x = s; sum = 0;
while (1) {
k = cur[x];
while (k > 0) {
if ((b[k] > 0)&&(dist[a[k]] == dist[x]-1)) break;
k = next[k];
}
if (k > 0) {
cur[x] = k;
fa[a[k]] = k;
dat[a[k]] = min(dat[x],b[k]);
x = a[k];
if (x == t) {
sum = sum+dat[x];
while (x!=s) {
b[fa[x]] = b[fa[x]]-dat[t];
b[fa[x] xor 1] = b[fa[x] xor 1]+dat[t];
x = a[fa[x] xor 1];
}
}
} else {
count[dist[x]]--;
if (count[dist[x]] == 0) return sum;
k = last[x];
dist[x] = t+1;
while (k!=0) {
if ((b[k] > 0)&&(dist[a[k]]+1 < dist[x])) {
dist[x] = dist[a[k]]+1;
cur[x] = k;
}
k = next[k];
}
count[dist[x]]++;
if (dist[s] > t) return sum;
if (x != s) x = a[fa[x] xor 1];
}
}
}
int main() {
/*
important
s better start from 1
tot start from 1!!
*/
int tt;
scanf("%d", &tt);
for (int cases = 1; cases <= tt; cases++) {
printf("Case #%d: ", cases);
scanf("%d %d %d", &n, &m, &l);
for (int i = 1; i <= n; i++) {
scanf("%d %d", &aa[i].pay, &aa[i].t);
aa[i].index = i;
}
std::sort(aa+1, aa+1+n);
for (int i = 1; i <= m; i++) {
scanf("%d %d", &bb[i].pro, &bb[i].num);
for (int j = 1; j <= bb[i].num; j++)
scanf("%d", &bb[i].index[j]);
}
all = false;
for (int i = 1; i <= n; i++) if (i == n || aa[i].t != aa[i+1].t){
memset(last, 0, sizeof(last));
memset(b, 0, sizeof(b));
memset(a, 0, sizeof(a));
memset(flag, 0, sizeof(flag));
tot = 1;
for (int j = 1; j <= i; j++) {
insert(1, aa[j].index+1, aa[j].pay);
flag[aa[j].index] = true;
}
sum = 0;
for (int j = 1; j <= m; j++) {
bool ok = true;
for (int k = 1; k <=bb[j].num; k++) if (!flag[bb[j].index[k]]) {
ok = false; break;
}
if (!ok) continue;
for (int k = 1; k <= bb[j].num; k++) {
insert(1+bb[j].index[k], 1+n+j, 1000000);
}
insert(1+n+j, 1+n+m+1, bb[j].pro);
sum = sum+bb[j].pro;
}
sum = sum-sap(1, 1+n+m+1);
if (sum >= l) {
printf("%d %d\n", aa[i].t, sum);
all = true;
break;
}
}
if (!all) printf("impossible\n");
}
}