zoukankan      html  css  js  c++  java
  • P3980 [NOI2008]志愿者招募 网络流

       

    题意: 一共有n 天  每天需要Ai个志愿者   

    有m种志愿者 每种志愿者可以从  第si 天工作到ti 天  每个需要ci元     问花最少的钱满足每天的需求

    显然是费用流

    如果正常连边的话  每个志愿者对其辐射的天非常难处理 

    可以采用时间轴的连法:

    源点连第一天

    汇点连最后一天

    容量为INF费用为0

    这样跑网络流是沿时间流的(就是依次解决每一天的问题)

    然后每一天向后一天连一条容量为INF-a[i]

    费用为0的边

    为什么容量为INF-a[i]

    这就相当于少了a[i]

    得用带权边补全INF

    这就是志愿者连续干时沿这条边跑

    因为连续干不花钱

    所以优先选这种边

    然后将每一类志愿者s[i]与t[i]+1连一条容量为

    INF花费为c[i]的边

    当连续干的人不够时

    就得使劲往里塞人

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=100001;
    
    ll maxflow,mincost;
    int last[N],pre[N],dis[N],flow[N];
    bool vis[N];
    struct Edge{
        int next,to,flow,dis;
    }edge[N<<1];
    int pos=1,head[N];
    void init()
    {
        pos=1;
        CLR(head,0);
        mincost=maxflow=0;
    }
    queue <int> q;
    void add(int from,int to,int flow,int dis)//flow流量 dis费用
    {
        edge[++pos].next=head[from];
        edge[pos].flow=flow;
        edge[pos].dis=dis;
        edge[pos].to=to;
        head[from]=pos;
    
        edge[++pos].next=head[to];
        edge[pos].flow=0;
        edge[pos].dis=-dis;
        edge[pos].to=from;
        head[to]=pos;
    
    }
    bool spfa(int s,int t)
    {
        CLR(dis,0x3f);
        CLR(flow,0x3f);
        CLR(vis,0);
        while (!q.empty()) q.pop();
        dis[s]=0; pre[t]=-1; q.push(s); vis[s]=1;
        int tot=0;
        while (!q.empty())
        {
            int now=q.front(); q.pop(); vis[now]=0;
            for (int i=head[now]; i; i=edge[i].next)
            {
                int to=edge[i].to;
                if  (edge[i].flow>0 && dis[to]>dis[now]+edge[i].dis)
                {
                    dis[to]=edge[i].dis+dis[now];
                    flow[to]=min(edge[i].flow,flow[now]);
                    last[to]=i;
                    pre[to]=now;
                    if (!vis[to])
                    {
                        q.push(to); vis[to]=1;
                    }
                }
            }
        }
        return pre[t]!=-1;
    }
    void MCMF(int s,int t)
    {
        while (spfa(s,t))
        {
            int now=t;
            maxflow+=flow[t];
            mincost+=flow[t]*dis[t];
            while (now!=s)
            {
                edge[last[now]].flow-=flow[t];//dis . flow
                edge[last[now]^1].flow+=flow[t];
                now=pre[now];
            }
        }
    }
    int a,b,s,t,n,m,c,x;
    
    int main()
    {
        RII(n,m);
        rep(i,1,n)RI(x),add(i,i+1,inf-x,0);
        while(m--)
        {
            RIII(a,b,c);
            add(a,b+1,inf,c);
        }
        s=n+2,t=s+1;
        add(s,1,inf,0);add(n+1,t,inf,0);
        MCMF(s,t);
        printf("%lld
    ",mincost);
        return 0;
    }
    View Code
  • 相关阅读:
    2017ccpc全国邀请赛(湖南湘潭) E. Partial Sum
    Codeforces Round #412 C. Success Rate (rated, Div. 2, base on VK Cup 2017 Round 3)
    2017 中国大学生程序设计竞赛 女生专场 Building Shops (hdu6024)
    51nod 1084 矩阵取数问题 V2
    Power收集
    红色的幻想乡
    Koishi Loves Segments
    Wood Processing
    整数对
    Room and Moor
  • 原文地址:https://www.cnblogs.com/bxd123/p/11252086.html
Copyright © 2011-2022 走看看