建图。
给每天建立两个节点Di,Si,分别表示租车公司内的车,当天归还了的车。源点S到第一天D1连接的是汽车公司的信息,Di->Dj的容量INF,花费为0,表示租车公司里的车可以不租出去,存在公司里。
Si->Dj表示归还的车可以在第(i + di + 1)天被再次租出去。每个Di->T连有一条当前的计划租出数。
最小费用最大流,跑完后,检查Di->T的边是不是满流,如果不是说明某一天不能完成计划的任务,无解。
下面是个例子,对应第一个输入数据。
3 2 1
10 20 30
40 90 15 100
1 5
#include
#include
#include
#include
#include
#define fi first
#define se second
#define pii pair
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 200+10;
int N, C, R;
// 图
struct Edge{
int u,v,cap,flow,cost;
Edge(int u, int v, int cap, int f, int cost):u(u),v(v),cap(cap),flow(f),cost(cost){}
};
vector edges;
vector G[maxn];
void init(int a){
for(int i = 0; i < a; ++i) G[i].clear();
edges.clear();
}
void addEdge(int u, int v, int cap, int cost){
edges.push_back(Edge(u,v,cap,0,cost));
edges.push_back(Edge(v,u,0,0,-cost));
int m = edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
int pre[maxn], dis[maxn], asc[maxn], inq[maxn];
bool Bellman(int s, int t, int& flow, LL& cost){
for(int i = 0; i < N*2+2; ++i){ dis[i] = INF; inq[i] = 0; }
queue Q;
Q.push(s);
dis[s] = 0; inq[s] = 1; asc[s] = INF;
while(!Q.empty()){
int x = Q.front(); Q.pop();
inq[x] = 0;
for(int i = 0; i < G[x].size(); ++i){
Edge& e = edges[G[x][i]];
if(dis[e.v] > dis[x] + e.cost&&e.cap > e.flow){
dis[e.v] = dis[x] + e.cost;
pre[e.v] = G[x][i];
asc[e.v] = min(asc[x], e.cap - e.flow);
if(!inq[e.v]){ Q.push(e.v); inq[e.v] = 1;}
}
}
}
if(dis[t] == INF) return false;
flow += asc[t];
cost+= (LL)asc[t] * (LL)dis[t];
for(int u = t; u != s; u = edges[pre[u]].u){
edges[pre[u]].flow += asc[t];
edges[pre[u]^1].flow -= asc[t];
}
return true;
}
int MCMF(int s, int t, LL& cost){
int flow = 0; cost = 0;
while(Bellman(s, t, flow, cost));
return flow;
}
int main()
{
freopen("in.txt","r",stdin);
int T; scanf("%d",&T);
int kase = 1;
while(T--){
scanf("%d%d%d",&N,&C,&R);init(2*N+2);
int s = 0, t = 2*N+1;
int sum = 0;
for(int i = 1; i <= N; ++i) {
int x; scanf("%d",&x); addEdge(s, i, x, 0); // s -> Q
if(i < N) addEdge(N+i, N+i+1, INF, 0); // gi -> gj
addEdge(N+i, t, x, 0); // g -> t
sum+= x;
}
for(int i = 1; i <= C; ++i) {
int a,b; scanf("%d%d", &a, &b); addEdge(s, N+1, a, b); // s -> g
}
for(int i = 0; i < R; ++i){
int d, s; scanf("%d%d", &d, &s);
for(int j = 1; j <= N; ++j){
if(j + d + 1 <= N) addEdge(j, N+j+d+1, INF, s); // q -> g
}
}
LL ans;
int maxflow = MCMF(s, t, ans);
printf("Case %d: ", kase++);
if(sum != maxflow) printf("impossible\n"); // 检查
else printf("%lld\n",ans);
}
return 0;
}