/*
AIZU 2266
最小花费=最大节省
考虑可以节省M-1个球的花费。
s-1: (M-1,0)
i-i+1: (inf,0)
a[i]=a[j]时: i-(j-1): (1,-w[a[i]])
// 全部箱子分成M-1个不动的箱子和一个动的箱子
连到j-1并不意味着到j的时候完全取出,而是挪到了可以动的箱子,
这样子不动的箱子就可以留给j-1秒可能加入的不动点。
如果i-j连的话,如果在第j-1秒加入一个长时间不动的球那就会把他加入可动的箱子里。
1 2 3 1 2 3 M=2
如果1 4 连, 3 5 连那么1 3不能共存这样子不对的。
1 3连,2 4连,3 5连, 3秒时1 3 可以共存在不同属性箱子中。
动 不动 花费
add1 1 10
2 2 1 20
3 1 3 30
1 1 3
2 2 3 20
3 2 3
*/
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 1<<30;
const int mmax = 20000020;
const int nmax = 11100;
int N,M,K;
int w[nmax],a[nmax];
int nex[nmax];
struct Edge{int u,v,cap,cost,nex;};
Edge e[mmax];
int etot=0;
int head[nmax];
int dist[nmax],inq[nmax],pre[nmax],e_used[nmax];
//pre:最短路前向点 e_used:到i点前一个用过的边
int max_flow,min_cost=0;
void init();
void addedge(int u,int v,int cap,int cost);
bool spfa(int s,int t);
void flow_change(int s,int t);
void mincost_maxflow(int s,int t);
int main(){
int x,tot=0;
scanf("%d%d%d",&M,&N,&K);
for(int i=1;i<=N;i++){
scanf("%d",&w[i]);
}
init();
for(int i=1;i<=K;i++){
scanf("%d",&a[i]);
}
K=unique(a+1,a+1+K)-a-1;
memset(nex,-1,sizeof(nex));
addedge(0,1,M-1,0);
for(int i=1;i<=K;i++){
tot+=w[a[i]];
if(nex[a[i]]!=-1)
addedge(nex[a[i]],i-1,1,-w[a[i]]);
nex[a[i]]=i;
addedge(i,i+1,inf,0);
}
mincost_maxflow(0,K);
printf("%d\n",tot+min_cost);
return 0;
}
void init(){
max_flow=min_cost=0;
etot=1;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost){
//printf("%d %d %d %d\n",u,v,cap,cost);
e[++etot].u=u; e[etot].v=v; e[etot].cap=cap; e[etot].cost=cost;
e[etot].nex=head[u];
head[u]=etot;
e[++etot].u=v; e[etot].v=u; e[etot].cap=0; e[etot].cost=-cost;
e[etot].nex=head[v];
head[v]=etot;
}
bool spfa(int s,int t){
for(int i=s;i<=t;i++)dist[i]=inf;
memset(inq,0,sizeof(inq));
memset(pre,-1,sizeof(pre));
queue<int> q;
dist[s]=0;
q.push(s);
inq[s]=1;
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=0;
for(int i=head[u];i!=-1;i=e[i].nex){
int v=e[i].v;
if(e[i].cap>0&&dist[v]>dist[u]+e[i].cost){
dist[v] = dist[u]+e[i].cost;
pre[v] = u;
e_used[v] = i;
if(!inq[v]){
inq[v] = 1;
q.push(v);
}
}
}
}
return pre[t]!=-1;
}
void flow_change(int s,int t){
int u,f=inf;
for(u=t; u!=s; u=pre[u]){
f=min(f,e[e_used[u]].cap);
}
max_flow+=f;
for(u=t; u!=s; u=pre[u]){
e[e_used[u]].cap -= f;
e[e_used[u]^1].cap += f;
min_cost += f*e[e_used[u]].cost;
}
}
void mincost_maxflow(int s,int t){
while(spfa(s,t)){
flow_change(s,t);
}
}
[AIZU 2266]Cache Strategy(最大权区间选择)

最新推荐文章于 2018-09-06 18:19:02 发布
