【Luogu】P2488工作安排(费用流)

  题目链接

  这题……费用流即可……(哇啊要被打死辣)

  然而我printf("%d")爆零四次

  好的心如死灰

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define maxn 1000010
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct Edge{
    long long next,from,to,val,dis;
}edge[maxn*2];
long long head[maxn],num;
inline void addedge(long long from,long long to,long long val,long long dis){
    edge[++num]=(Edge){head[from],from,to,val,dis};
    head[from]=num;
}
inline void add(long long from,long long to,long long val,long long dis){
    addedge(from,to,val,dis);
    addedge(to,from,0,-dis);
}

inline long long count(long long i){    return i&1?i+1:i-1;    }

long long Start,End;
long long dis[maxn];
bool vis[maxn];
long long pre[maxn];
long long flow[maxn];

long long spfa(){
    memset(dis,127/2,sizeof(dis));    dis[Start]=0;    flow[Start]=dis[1];
    memset(pre,0,sizeof(pre));
    queue<long long>q;    q.push(Start);
    while(!q.empty()){
        long long from=q.front();q.pop();    vis[from]=0;
        if(flow[from]==0)    continue;
        for(long long i=head[from];i;i=edge[i].next){
            long long to=edge[i].to;
            if(dis[to]<=dis[from]+edge[i].dis||edge[i].val<=0)    continue;
            dis[to]=dis[from]+edge[i].dis;
            pre[to]=i;    flow[to]=min(flow[from],edge[i].val);
            if(vis[to])    continue;
            vis[to]=1;    q.push(to);
        }
    }
    if(pre[End]==0)    return 0;
    long long now=End;
    while(now!=Start){
        long long ret=pre[now];
        edge[ret].val-=flow[End];    edge[count(ret)].val+=flow[End];
        now=edge[ret].from;
    }
    return dis[End]*flow[End];
}

long long s[maxn];

int main(){
    long long m=read(),n=read();End=n+m+1;
    for(long long i=1;i<=n;++i){
        long long x=read();
        add(i+m,End,x,0);
    }
    for(long long i=1;i<=m;++i)
        for(long long j=1;j<=n;++j){
            long long x=read();
            if(x)    add(i,j+m,0x7fffffff,0);
        }
    for(long long i=1;i<=m;++i){
        long long sum=read();
        for(long long j=1;j<=sum;++j)    s[j]=read();
        for(long long j=1;j<=sum;++j){
            long long x=read();
            add(Start,i,s[j]-s[j-1],x);
        }
        long long x=read();
        add(Start,i,0x7fffffff,x);
    }
    long long ans=0;
    while(1){
        long long now=spfa();
        if(now==0)    break;
        ans+=now;
    }
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-04-17 19:08  Konoset  阅读(154)  评论(0编辑  收藏  举报