bzoj2879: [Noi2012]美食节

题目链接

bzoj2879: [Noi2012]美食节

题解

除了数据范围和修车一样
对于没人没个要求拆点间图
增光一条后更改下次增广费用
然后要返向啊,不然就T了,好坑啊
然后在西校写代码在东校调试,代码格式好鬼畜啊

代码

#include<queue> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
 
inline int read() { 
        int x = 0; 
        char c = getchar(); 
        while(c < '0' || c > '9')c = getchar(); 
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
        return x ; 
}
const int maxn = 100007 ; 
struct Node {
        int next,u,flow,v,cost;
}edge[maxn << 2 + 1]; int num = 1,head[maxn]; 
inline void add_edge(int u,int v,int flow,int cost) { 
        edge[++ num].v = v;edge[num].u = u;edge[num].cost = cost,edge[num].flow = flow,edge[num].next = head[u];head[u] = num;
} 
inline void Add(int u,int v,int flow,int cost) {add_edge(u,v,flow,cost);add_edge(v,u,0,-cost);  } 
int c[maxn],p[105][105],dis[maxn],pre[maxn];bool vis[maxn];  
int que[maxn]; 
int n,m,tot = 0,S,T,ans;
bool spfa() {
       for(int i = 0;i <= T;++ i) vis[i] = 0,dis[i] = 0x3f3f3f3f;    
        dis[S] = 0;vis[S] = 1;
        int l = 0,r = 1;
    que[l] = S;
    while(l < r) {
                int u = que[l ++];if(l == T) l = 0; 
            for(int i = head[u];i;i = edge[i].next) {
                    int v = edge[i].v;
                    if(edge[i].flow > 0 && dis[v] > dis[u] + edge[i].cost) {
                        pre[v] = i;
                        dis[v] = dis[u] + edge[i].cost; 
                        if(!vis[v]){que[r ++] = v,vis[v] = 1;if(r == T)r = 0;} 
                    }
            }   
            vis[u] = 0;
        }
        if(dis[T] == 0x3f3f3f3f) return false; 
        else return true; 
} 
void MCMF() { 
        while(spfa()) { 
            int MIN = 0x7fffffff,y,a,b;
            for(int i = pre[T];i;i = pre[edge[i].u])  
                MIN = std::min(MIN,edge[i].flow); 
        for(int i = pre[T];i;i = pre[edge[i].u]) 
                edge[i].flow -= MIN ,edge[i ^ 1].flow += MIN,ans += edge[i].cost * MIN;
            int x = edge[pre[T]].u; 
        Add(x + 1,T,1,0); 
        for(int i = 1;i <= n;++ i) {
                Add(m * tot + i,x + 1,1,p[i][x / tot + 1] * (x % tot + 1)); 
            }       
    }
} 
int main() { 
        n = read(),m = read(); 
        S = 0;T = 100001;
        for(int i = 1;i <= n;++ i) c[i] = read(), tot += c[i]; 
        for(int i = 1;i <= n;++ i) {
        Add(S,i + tot * m,c[i],0);
                for(int j = 1;j <= m;++ j) {
                p[i][j] = read(); 
            Add(i + tot * m,(j - 1) * tot + 1,1,p[i][j]);       
        }
    }    
        for(int i = 1;i <= m;++ i) Add((i - 1) * tot + 1,T,1,0); 
        MCMF(); 
        printf("%d\n",ans);  
    return 0; 
}
/*
*/
posted @ 2018-05-20 17:59  zzzzx  阅读(121)  评论(0编辑  收藏  举报