• [SDOI2011]工作安排


    原题的话,由于保证了wi<wi+1,是一个比较simple的费用流啦。

    如果不保证wi递增的话,也可以有一个比较暴力的复杂度和流量相关的做法。

    #include<iostream>
    #include<cctype>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #define N 220000
    #define M 220000
    #define L 200000
    #define eps 1e-7
    #define inf 1e9+7
    #define ll long long
    using namespace std;
    inline int read()
    {
        char ch=0;
        int x=0,flag=1;
        while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
        while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*flag;
    }
    struct edge
    {
        int to,nxt,flow,w;
    }e[M];
    int num,head[N];
    inline void add(int x,int y,int w,int z)
    {
        e[++num]=(edge){y,head[x],w,+z};head[x]=num;
        e[++num]=(edge){x,head[y],0,-z};head[y]=num;
    }
    queue<int>q;
    bool in_queue[N];
    int s,t,T[N],W[N],dis[N],pre[N],last[N],flow[N];
    bool spfa()
    {
        for(int i=0;i<=t;i++)dis[i]=flow[i]=inf;
        dis[s]=0;q.push(s);in_queue[s]=true;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();in_queue[x]=false;
            for(int i=head[x];i!=-1;i=e[i].nxt)
            {
                int to=e[i].to;
                if(dis[to]>dis[x]+e[i].w&&e[i].flow)
                {
                    dis[to]=dis[x]+e[i].w;
                    flow[to]=min(flow[x],e[i].flow);
                    pre[to]=x;last[to]=i;
                    if(!in_queue[to])q.push(to),in_queue[to]=true;
                }
            }
        }
        return dis[t]<inf;
    }
    void dfs(int x)
    {
        if(x==s)return;
        int id=last[x];
        e[id].flow-=flow[t];
        e[id^1].flow+=flow[t];
        dfs(pre[x]);
    }
    int main()
    {
        num=-1;memset(head,-1,sizeof(head));
        int m,n;
        m=read();n=read();s=n+m+1;t=n+m+2;
        for(int i=1;i<=n;i++)add(i+m,t,read(),0);
        for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)
        if(read())add(i,j+m,inf,0);
        for(int i=1;i<=m;i++)
        {
            int k=read();
            for(int j=1;j<=k;j++)T[j]=read();T[k+1]=inf;
            for(int j=1;j<=k+1;j++)W[j]=read();
            for(int j=1;j<=k+1;j++)add(s,i,T[j]-T[j-1],W[j]);
        }
        ll ans=0;
        while(spfa())
        {
            ans+=dis[t]*flow[t];
            dfs(t);
        }
        printf("%lld",ans);
        return 0;
    }
    
  • 相关阅读:
    redisserver 双击闪退
    PHP QueryList采集器
    【ubuntu】配置国内源
    【ffmpeg基础知识】文件的删除和重命名
    【ffmpeg基础知识】打印视频meta信息
    Ubuntu下pkgconfig环境变量配置
    音视频基础知识
    【linux小技巧】返回上一个目录,vi默认显示行号,vi多窗口
    【ffmpeg基础知识】ffmpeg操作目录实现list
    【ffmpeg基础知识】日常日志
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/10082849.html
Copyright © 2020-2023  润新知