同上道题的建模方法,不过这道题的数据较大,要用动态加边,判断每位厨师的最后一个点是否已用,如果用过,才添加下一个点
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 1000
#define maxm 180000
#define inf 0x7fffffff
using namespace std;
struct edges{ int to,cap,dist,next;
}edge[maxm];int s,t,next[maxn],l;
int addedge(int from,int to,int cap,int dist){
l++;
edge[l*2]=(edges){to,cap,dist,next[from]};
edge[l*2+1]=(edges){from,0,-dist,next[to]};
next[from]=l*2;next[to]=l*2+1;
return 0;
}bool b[maxn];int dist[maxn],node,way[maxn];
queue<int> q;
bool spfa(){ for (int i=1;i<=node;i++) dist[i]=inf;
memset(b,0,sizeof(b));
dist[s]=0;
q.push(s);
while (!q.empty()){
int u=q.front();q.pop();
b[u]=0;
for (int i=next[u];i;i=edge[i].next)
if (edge[i].cap&&dist[u]+edge[i].dist<dist[edge[i].to]) {
dist[edge[i].to]=dist[u]+edge[i].dist;
way[edge[i].to]=i;
if (!b[edge[i].to]){
b[edge[i].to]=1;q.push(edge[i].to);
}
}
}
if (dist[t]==inf) return 0;
return 1;
}int n,m,ti[50][110],last[110],cnt[110];
int mcmf(){
int cost=0;
while (spfa()){
cost+=dist[t];
int x=t;
while (x!=s){
edge[way[x]].cap-=1;
edge[way[x]^1].cap+=1;
x=edge[way[x]^1].to;
}
for (int i=1;i<=m;i++)
if (!edge[last[i]].cap) {
addedge(s,++node,1,0);
last[i]=l*2;cnt[i]++;
for (int j=1;j<=n;j++) addedge(node,2+j,1,cnt[i]*ti[j][i]);
}
}
return cost;
}int main(){
scanf("%d%d",&n,&m);
s=1;t=2;node=n+2+m;
for (int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
addedge(i+2,t,x,0);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%d",&ti[i][j]);
for (int i=1;i<=m;i++) {
cnt[i]=1;
addedge(s,i+2+n,1,0);
last[i]=l*2;
for (int j=1;j<=n;j++) addedge(i+2+n,2+j,1,cnt[i]*ti[j][i]);
}
printf("%d\n",mcmf());
return 0;
} |