题解 洛谷P1251 网络流24题.01【餐巾计划问题】

\(\huge\mathbb{DESCRIPTION}\)
编号:洛谷\(P1251\)\(LOJ6008\)(与洛谷上本题输入顺序有不同)
算法:最小费用最大流、贪心
来源:网络流\(24\)
\(\huge\mathbb{SOLUTION}\)
这道题目我们可以用最小费用最大流来解决。
首先,我们要考虑如何建图
我们可以连一下的几类边:

\(Number\) \(From\) \(To\) \(Stream\) \(Cost\)
1 源点\(Start\) \(i\)天的早上 \(INF\) \(Buy\)
2 源点\(Start\) \(i\)天的晚上 \(Should_i\) \(0\)
3 \(i\)天的晚上 \(i+1\)天的晚上 \(INF\) \(0\)
4 \(i\)天的晚上 \(i+QuickTime\)天的晚上 \(INF\) \(QuickCost\)
5 \(i\)天的晚上 \(i+SlowTime\)天的晚上 \(INF\) \(SlowCost\)
6 \(i\)天的早上 汇点\(End\) \(Should_i\) \(0\)
思路似乎一下子就出来了。
建完图以后跑一遍最小费用最大流的模板,一路增广,结果就出来了。
\(P.S.\)如果您在洛谷上得到了\(80\)分,可能是没有开\(long long\)的锅\(QωQ\)
\(AC\)链接
\(\huge\mathbb{CODE}\)
#include<bits/stdc++.h>
#define INF 0x7ffffff
#define MAX 10001
using namespace std;
int TotalPoint;
int Start,End;
long long Ans,AllCost;
bool Visit[MAX];
bool VisitDfs[MAX];
long long Dist[MAX];
int Days;
int Should[MAX];
int Buy,QuickTime,QuickCost,SlowTime,SlowCost;
vector<int>Edge[MAX];
vector<int>Stream[MAX];
vector<int>Cost[MAX];
vector<int>Size[MAX];
inline void AddEdge(int From,int To,int NowStream,int NowCost)
{
    Edge[From].push_back(To);
    Edge[To].push_back(From);
    Stream[From].push_back(NowStream);
    Stream[To].push_back(0);
    Cost[From].push_back(NowCost);
    Cost[To].push_back(-NowCost);
    Size[From].push_back(Edge[To].size()-1);
    Size[To].push_back(Edge[From].size()-1);
}
inline bool Spfa(int Start,int End)
{
    register queue<int>Queue;
    register int i;
    for(i=1;i<=TotalPoint;i++)
    {
        VisitDfs[i]=false;
        Visit[i]=false;
        Dist[i]=INF;
    }
    Visit[Start]=true;
    Dist[Start]=0;
    Queue.push(Start);
    while(!Queue.empty())
    {
        register int Top;
        Top=Queue.front();
        Queue.pop();
        Visit[Top]=false;
        for(i=0;i<Edge[Top].size();i++)
        {
            register int Next;
            Next=Edge[Top][i];
            if(Dist[Top]+Cost[Top][i]<Dist[Next]&&Stream[Top][i])
            {
                Dist[Next]=Dist[Top]+Cost[Top][i];
                if(!Visit[Next])
                {
                    Visit[Next]=true;
                    Queue.push(Next);
                }
            }
        }
    }
    return Dist[End]!=INF;
}
inline int Dfs(int Now,int End,int Min)
{
    if(!Min||Now==End)
    {
        return Min;
    }
    register int Return;
    Return=0;
    VisitDfs[Now]=1;
    register int i;
    for(i=0;i<Edge[Now].size();i++)
    {
        register int Next=Edge[Now][i];
        if(Dist[Now]+Cost[Now][i]==Dist[Next]&&Stream[Now][i]&&!VisitDfs[Next])
        {
            register int MinStream;
            MinStream=Dfs(Next,End,min(Min,Stream[Now][i]));
            Stream[Now][i]-=MinStream;
            Stream[Next][Size[Now][i]]+=MinStream;
            Min-=MinStream;
            Return+=MinStream;
            AllCost+=MinStream*Cost[Now][i];
        }
    }
    return Return;
}
inline void Mcmf()
{
    while(Spfa(Start,End))
    {
        Ans+=Dfs(Start,End,INF);
    }
}
int main(void)
{
    register int i;
    cin>>Days; 
    for(i=1;i<=Days;i++)
    {
	cin>>Should[i];
    }
    cin>>Buy>>QuickTime>>QuickCost>>SlowTime>>SlowCost;
    Start=0;
    End=2*Days+1;
    for(i=1;i<=Days;i++)
    {
    	AddEdge(Start,i,Should[i],0);
    }
    for(i=1;i<=Days;i++)
    {
        AddEdge(i+Days,End,Should[i],0);
    }
    for(i=1;i<=Days;i++)
    {
    	if(i+1<=Days)
    	{
    	    AddEdge(i,i+1,INF,0);
        }
        if(i+QuickTime<=Days)
        {
            AddEdge(i,i+QuickTime+Days,INF,QuickCost);
        }
        if(i+SlowTime<=Days)
        {
            AddEdge(i,i+SlowTime+Days,INF,SlowCost);
        }
        AddEdge(0,i+Days,INF,Buy);
    }
    TotalPoint=2*Days+1;
    Mcmf();
    cout<<AllCost<<endl;
    return 0;
}
posted @ 2020-08-14 22:23  Bushuai_Tang  阅读(99)  评论(0编辑  收藏  举报