网络流的应用太多了,对于各种网络流的题目,要熟练运用建模思想,将实际问题转化为网络流模型。
GO:洛谷
我们将问题划分成几个子问题:
1.“餐巾的数量”,“需要的费用”,“天数”分别指代什么?
2.快洗,慢洗会对哪些状态造成影响?
3.如何建立(记录)影响与影响间的关系
……
首先,分析题意,不难发现这是一道最小费用最大流的问题。我们按贪心的思想看,每天分配好所需要的餐巾是基本任务,而让所花的费用最小是优化方案。
因此,分配餐巾对应着网络中的流,而费用就是费用。
快洗,慢洗等状态会为未来的某一天增加餐巾,因此影响的对象是未来洗完的那一天。
我们将一天分为两个状态:消耗餐巾和送出餐巾。
消耗餐巾,在网络流中即为消耗流(使用餐巾),而送出对应着增加花费(洗餐巾),这样就将模型初步建立完成了。
而对于程序本身而言,一个流为inf的边,代表可以随便走,最终这条边也不会被删去,但是只要走过了就会消耗费用,比如将今天的餐巾送出去洗。而一个流为0,费用为0的边,可以当做一个状态的转移,比如将今天的餐巾堆积到明天,既不消耗费用也不使用餐巾。所以限制好一些条件,让程序自己完成任务即可,这是网络流最大的魅力所在。
1 #include<bits/stdc++.h>
2 #define f(i,a,b) for(int i=a;i<=b;i++)
3 using namespace std;
4 typedef long long ll;
5 const int inf=1e9;
6 const int N=2e5+10;
7 int n,s,t,vf,tf,vs,ts,co,cnt=-1,sum;
8 int head[N],vis[N],l[N],pre[N],flow[N],dis[N];
9 struct edge{int to,next,f,w;}e[N];
10 void addedge(int from,int to,int f,int w){
11 e[++cnt]=(edge){to,head[from],f,w}; head[from]=cnt;
12 }
13 queue<int> q;
14 bool spfa(){
15 memset(vis,0,sizeof(vis));
16 memset(dis,0x7f,sizeof(dis));
17 dis[s]=pre[t]=0;
18 q.push(s);
19 flow[s]=inf;
20 vis[s]=1;
21 while(!q.empty()){
22 int u=q.front();
23 vis[u]=0;
24 for(int i=head[u];i!=-1;i=e[i].next){
25 int v=e[i].to,f=e[i].f,w=e[i].w;
26 if(f>0&&dis[v]>dis[u]+w){
27 dis[v]=dis[u]+w;
28 pre[v]=u;
29 l[v]=i;
30 flow[v]=min(flow[u],f);
31 if(!vis[v]){
32 q.push(v);
33 vis[v]=1;
34 }
35 }
36 }
37 q.pop();
38 }
39 return pre[t];
40 }
41 void solve(){
42 ll ansc=0;
43 while(spfa()){
44 ansc+=flow[t]*dis[t];
45 for(int i=t;i!=s;i=pre[i]){
46 int ed=l[i];
47 e[ed].f-=flow[t];
48 e[ed^1].f+=flow[t];
49 }
50 }
51 printf("%lld",ansc);
52 }
53 int main(){
54 // freopen("dat.in","r",stdin);
55 memset(head,-1,sizeof(head));
56 scanf("%d",&n);
57 t=n<<1|1;s=0;
58 f(i,1,n){
59 scanf("%d",&sum);
60 addedge(s,i,sum,0);
61 addedge(i,s,0,0);
62 addedge(i+n,t,sum,0);
63 addedge(t,i+n,0,0);
64 }
65 scanf("%d%d%d%d%d",&co,&tf,&vf,&ts,&vs);
66 f(i,1,n){
67 if(i+1<=n) addedge(i,i+1,inf,0),addedge(i+1,i,0,0);
68 if(i+tf<=n) addedge(i,i+n+tf,inf,vf),addedge(i+n+tf,i,0,-vf);
69 if(i+ts<=n) addedge(i,i+n+ts,inf,vs),addedge(i+n+ts,i,0,-vs);
70 addedge(s,i+n,inf,co);
71 addedge(i+n,s,0,-co);
72 }
73 solve();
74 return 0;
75 }