• NOI2008 志愿者招募


    题目传送门

    Description

    一个项目分(n)天完成,每天需要(a_i)个志愿者。志愿者有(m)种招募方式,第(i)种从第(s_i)天工作到第(t_i)天,工资(c_i)元。求完成项目的最少花费。((nleq 10^3,mleq 10^4))

    Solution

    数据范围和题目描述都指向网络流,且是最小费用最大流。

    但如何建图?这就不显然了。

    以每天为一个节点,并建立源点和汇点。

    源点连第一天,最后一天连汇点,容量为(inf),费用为(0)

    每一天连后一天,容量为(inf-a_i),费用为(0)

    对于每一类志愿者,(s_i)(t_i),容量为(inf),费用为(c_i)

    然后跑最小费用最大流即可。

    为什么这样建图可行?不难发现,只要题目有解,最大流一定为(inf),也就是用有费用的流将所有的(a_i)都填满了。

    Code

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define int long long
    #define rep(i, a, b) for (register int i=(a); i<=(b); ++i)
    #define per(i, a, b) for (register int i=(a); i>=(b); --i)
    using namespace std;
    const int N=10005, M=200005, inf=1ll<<60;
    struct node{int to, nxt, flow, cost;}edge[M];
    int head[N], vis[N], last[N], pre[N], flow[N], cost[N];
    int a[N], s[M], t[M], c[M], n, m, cnt, S, T;
    void prep(){memset(head, -1, sizeof(head)); cnt=-1;}
    
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
        for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
        return x*f;
    }
    
    void add(int u, int v, int f, int w)
    {
        edge[++cnt]=(node){v, head[u], f, w}; head[u]=cnt;
        edge[++cnt]=(node){u, head[v], 0, -w}; head[v]=cnt;
    }
    
    bool spfa()
    {
        rep(i, 1, n+3) cost[i]=inf; cost[S]=0;
        memset(vis, 0, sizeof(vis)); vis[S]=1;
        rep(i, 1, n+3) flow[i]=inf;
        queue<int> q; q.push(S); pre[T]=-1;
        while (!q.empty())
        {
            int u=q.front(); q.pop();
            for (int i=head[u]; ~i; i=edge[i].nxt)
            {
                vis[u]=0;
                int v=edge[i].to, w=edge[i].cost, f=edge[i].flow;
                if (f>0 && cost[u]+w<cost[v]) 
                {
                    pre[v]=u; last[v]=i; cost[v]=cost[u]+w;
                    flow[v]=min(flow[u], f);
                    if (!vis[v]) vis[v]=1; q.push(v);
                }
            }
        }
        return ~pre[T];
    }
    
    int EK()
    {
        int maxflow=0, mincost=0;
        while (spfa())
        {
            maxflow+=flow[T]; mincost+=flow[T]*cost[T];
            int u=T;
            while (u^S)
            {
                edge[last[u]].flow-=flow[T];
                edge[last[u]^1].flow+=flow[T];
                u=pre[u];
            }
        }
        return mincost;
    }
    
    signed main()
    {
        prep(); n=read(); m=read(); S=n+2; T=n+3;
        rep(i, 1, n) a[i]=read();
        rep(i, 1, m) s[i]=read(), t[i]=read(), c[i]=read();
        add(S, 1, inf, 0); add(n+1, T, inf, 0);
        rep(i, 1, n) add(i, i+1, inf-a[i], 0);
        rep(i, 1, m) add(s[i], t[i]+1, inf, c[i]);
        printf("%lld
    ", EK());
        return 0;
    }
    
    
  • 相关阅读:
    Nginx 413 Request Entity Too Large
    Docker 搭建一个多端同步网盘-Nextcloud
    FTP主动模式(PORT)与被动模式(PASV)
    Linux安装与使用FTP服务-vsftpd
    Mac FTP工具推荐-Transmit
    Nginx配置动静分离
    Nginx解决跨域问题(CORS)
    CentOS 7 之找回失落的ifconfig
    CentOS 7 之安装篇
    深入研究MiniMVC之后续篇
  • 原文地址:https://www.cnblogs.com/ACMSN/p/10749941.html
Copyright © 2020-2023  润新知