題解 洛谷P1251 網路流24題.01【餐巾計劃問題】
阿新 • • 發佈:2020-08-15
\(\huge\mathbb{DESCRIPTION}\)
編號:洛谷\(P1251\)、\(LOJ6008\)(與洛谷上本題輸入順序有不同)
演算法:最小費用最大流、貪心
來源:網路流\(24\)題
\(\huge\mathbb{SOLUTION}\)
這道題目我們可以用最小費用最大流來解決。
首先,我們要考慮如何建圖。
我們可以連一下的幾類邊:
\(From\) | \(To\) | \(Stream\) | \(Cost\) |
---|---|---|---|
源點\(Start\) | 第\(i\)天的白天 | \(INF\) | \(Buy\) |
源點\(Start\) | 第\(i\)天的晚上 | \(Should[i]\) | \(0\) |
第\(i\)天的晚上 | 第\(i+1\)天的晚上 | \(INF\) | \(0\) |
第\(i\)天的晚上 | 第\(i+\)天的晚上 |
\(\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; }