zoukankan      html  css  js  c++  java
  • bzoj2879: [Noi2012]美食节

    费用流加动态建点。

    考虑加的点是倒数第几个做的菜,它对答案的共享就是i倍的时间。

    和bzoj1070修车那道题一样。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxk = 100 + 10;
    const int maxn = 10000 + 10;
    const int maxm = 2000000 + 10;
    const int inf = 0x3f3f3f3f;
    int g[maxn],v[maxm],next[maxm],c[maxm],f[maxm],eid;
    int n,m,res,p,vid,S,T;
    int id[maxk][1010],cnt[maxk];
    int a[maxk][maxk];
    int q[maxm],l,r,u;
    bool inque[maxn];
    int dist[maxn],pre[maxn];
    
    void addedge(int a,int b,int F,int C) {
        v[eid]=b; f[eid]=F; c[eid]=C;  next[eid]=g[a]; g[a]=eid++;    
        v[eid]=a; f[eid]=0; c[eid]=-C; next[eid]=g[b]; g[b]=eid++;
    }
    
    void build() {
        memset(g,-1,sizeof(g));
        scanf("%d%d",&n,&m);
        vid=n; S=0; T=maxn-10;
        for(int i=1,x;i<=n;i++) {
            scanf("%d",&x);
            addedge(S,i,x,0);
            p+=x;
        }
        for(int i=1;i<=m;i++) {
            id[i][++cnt[i]]=++vid;
            addedge(id[i][cnt[i]],T,1,0);
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
            scanf("%d",&a[i][j]);
            addedge(i,id[j][cnt[j]],1,a[i][j]);        
        }
    }
    
    void augment() {
        int aug=inf,cur=0;
        for(int i=T;i!=S;i=v[pre[i]^1]) aug=min(aug,f[pre[i]]);
        for(int i=T;i!=S;i=v[pre[i]^1]) {
            f[pre[i]]-=aug;
            f[pre[i]^1]+=aug;
            cur+=aug*c[pre[i]];
        }
        res+=cur;
    }
    
    int SPFA() {
        memset(dist,0x3f,sizeof(dist));    
        dist[S]=0;
        q[r++]=S; 
        while(l<r) {
            inque[u=q[l++]]=0;
            for(int i=g[u];~i;i=next[i]) if(f[i]&&dist[v[i]]>dist[u]+c[i])    {
                dist[v[i]]=dist[u]+c[i];
                pre[v[i]]=i;
                if(!inque[v[i]]) inque[q[r++]=v[i]]=1;
            }
        }
        //printf("test %d
    ",dist[T]);
        augment();
        return v[pre[T]^1];
    }
    
    void alter(int pos) {
        int x;
        for(int i=1;i<=m;i++) if(id[i][cnt[i]]==pos) {x=i; break;}
        id[x][++cnt[x]]=++vid;
        addedge(id[x][cnt[x]],T,1,0);
        for(int i=1;i<=n;i++) addedge(i,id[x][cnt[x]],1,a[i][x]*cnt[x]);
    }
    
    void solve() {
        res=0;
        for(int i=1;i<=p;i++) alter(SPFA());
        printf("%d
    ",res);
    }
    
    int main() {
        build();
        solve();    
        return 0;
    }
  • 相关阅读:
    Django入门
    RCNN 研究相关
    [Android UI]View滑动方式总结
    [Android UI]View基础知识
    [Android]Android开发艺术探索第1章笔记
    [Leetcode]017. Letter Combinations of a Phone Number
    java之this关键字
    POJ 1000 A+B
    [Leetcode]016. 3Sum Closest
    [Leetcode]015. 3Sum
  • 原文地址:https://www.cnblogs.com/invoid/p/5647737.html
Copyright © 2011-2022 走看看