[bzoj2245]工作安排
由于价格是单调递增的,因此可以直接建立Si条边,流量和价格依次为给定的函数即可
(如果价格不递增,可以考虑动态加边等操作)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1005 4 struct ji{ 5 int nex,to,len,cost; 6 }edge[N*N]; 7 queue<int>q; 8 int E,n,m,x,y,head[N],d[N],from[N],vis[N]; 9 long long ans; 10 void add(int x,int y,int z,int w){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 edge[E].len=z; 14 edge[E].cost=w; 15 head[x]=E++; 16 if (E&1)add(y,x,0,-w); 17 } 18 bool spfa(){ 19 memset(d,0x3f,sizeof(d)); 20 memset(vis,0,sizeof(vis)); 21 q.push(0); 22 d[0]=0; 23 while (!q.empty()){ 24 int k=q.front(); 25 q.pop(); 26 for(int i=head[k];i!=-1;i=edge[i].nex) 27 if ((edge[i].len)&&(d[edge[i].to]>d[k]+edge[i].cost)){ 28 d[edge[i].to]=d[k]+edge[i].cost; 29 from[edge[i].to]=i; 30 if (!vis[edge[i].to]){ 31 vis[edge[i].to]=1; 32 q.push(edge[i].to); 33 } 34 } 35 vis[k]=0; 36 } 37 return d[n+m+1]<0x3f3f3f3f; 38 } 39 int main(){ 40 scanf("%d%d",&n,&m); 41 memset(head,-1,sizeof(head)); 42 for(int i=1;i<=m;i++){ 43 scanf("%d",&x); 44 add(i+n,n+m+1,x,0); 45 } 46 for(int i=1;i<=n;i++) 47 for(int j=1;j<=m;j++){ 48 scanf("%d",&x); 49 if (x)add(i,j+n,0x3f3f3f3f,0); 50 } 51 for(int i=1;i<=n;i++){ 52 scanf("%d",&x); 53 for(int j=1;j<=x;j++)scanf("%d",&d[j]); 54 d[x+1]=0x3f3f3f3f; 55 for(int j=0;j<=x;j++){ 56 scanf("%d",&y); 57 add(0,i,d[j+1]-d[j],y); 58 } 59 } 60 while (spfa()){ 61 x=0x3f3f3f3f; 62 for(int i=n+m+1;i;i=edge[from[i]^1].to)x=min(x,edge[from[i]].len); 63 ans+=1LL*x*d[n+m+1]; 64 for(int i=n+m+1;i;i=edge[from[i]^1].to){ 65 edge[from[i]].len-=x; 66 edge[from[i]^1].len+=x; 67 } 68 } 69 printf("%lld",ans); 70 }