BZOJ 2879: [Noi2012]美食节

同上道题的建模方法,不过这道题的数据较大,要用动态加边,判断每位厨师的最后一个点是否已用,如果用过,才添加下一个点

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;
}

 

posted @ 2014-06-09 09:53  New_Godess  阅读(113)  评论(0编辑  收藏  举报