链接
http://www.lydsy.com/JudgeOnline/problem.php?id=2245
题解
直接建图跑费用流即可。
从S到每个人加容量为
ti−ti−1
费用为
wi
的边,人到对应的产品加边,产品到T加边。
代码
//费用流
//费用流
#include <cstdio>
#include <algorithm>
#include <queue>
#define maxn 1000000
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
int head[maxn], to[maxn], nex[maxn], tot=1, c[maxn], w[maxn], N, M, S, T, dist[maxn],
pre[maxn], in[maxn];
ll cost;
queue<int> q;
void adde(int a, int b, int cc, int ww)
{to[++tot]=b;c[tot]=cc;w[tot]=ww;nex[tot]=head[a];head[a]=tot;}
void adde2(int a, int b, int cc, int ww){adde(a,b,cc,ww);adde(b,a,0,-ww);}
bool spfa()
{
int i, p, x;
for(i=1;i<=T;i++)dist[i]=inf;
dist[S]=0;in[S]=1;q.push(S);
while(!q.empty())
{
in[x=q.front()]=0;q.pop();
for(p=head[x];p;p=nex[p])
if(c[p] and dist[to[p]]>dist[x]+w[p])
{
dist[to[p]]=dist[x]+w[p];
pre[to[p]]=p;
if(!in[to[p]])q.push(to[p]),in[to[p]]=1;
}
}
return dist[T]!=inf;
}
void augment()
{
int flow=inf, x;
for(x=T;x^S;x=to[pre[x] xor 1])flow=min(flow,c[pre[x]]);
for(x=T;x^S;x=to[pre[x] xor 1])c[pre[x]]-=flow, c[pre[x] xor 1]+=flow;
cost+=(ll)dist[T]*flow;
}
void init()
{
int i, j, x, s, t[10]={0}, w[10];
scanf("%d%d",&M,&N);
S=M+N+10, T=S+1;
for(i=1;i<=N;i++)scanf("%d",&x),adde2(M+i,T,x,0);
for(i=1;i<=M;i++)for(j=1;j<=N;j++)
{
scanf("%d",&x);
if(x)adde2(i,M+j,inf,0);
}
for(i=1;i<=M;i++)
{
scanf("%d",&s);
for(j=1;j<=s;j++)scanf("%d",t+j);
for(j=1;j<=s+1;j++)scanf("%d",w+j);
for(j=1;j<=s;j++)adde2(S,i,t[j]-t[j-1],w[j]);
adde2(S,i,inf,w[s+1]);
}
}
int main()
{
init();
while(spfa())augment();
printf("%lld",cost);
return 0;
}