洛谷 P1251 餐巾计划问题(费用流)
题意:中文题
思路:直接按照题目上的描述建费用流即可,不过流量上限还是挺有意思的
代码:(爆了4 5发long long)
#include <bits/stdc++.h> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct Min_cost_flow { int S,T; long long ans=0; int vis[100010],vis2[100010]; int d[100010],head[100010],to[100010],nextt[100010],w[100010],cost[100010]; int tot = 2; int inf=0x7fffffff; void init(int _s,int _t) { S=_s;T=_t; memset(head,0,sizeof(head)); ans=0;tot=2; } void add(int u,int v,int cap,int co) { cost[tot]=co; w[tot]=cap; to[tot]=v; nextt[tot]=head[u]; head[u]=tot++; cost[tot] = -co; w[tot]=0; to[tot]=u; nextt[tot]=head[v]; head[v]=tot++; } bool spfa() { memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); for(int i = 1;i<=T;i++)d[i]=inf; queue<int> q; q.push(S); d[S]=0; vis[S]=1; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i = head[u];i;i=nextt[i]) { int v = to[i]; if(w[i] && d[v]>d[u]+cost[i]) { d[v]=d[u]+cost[i]; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return d[T]<inf; } int dfs(int u,int f) { if(u==T) { ans+=d[u] * f; return f; } int res=0; vis2[u]=1; for(int i=head[u];i;i=nextt[i]) { int v = to[i]; if (w[i] && !vis2[v] && d[v]==d[u]+cost[i]) { int temp=dfs(v,min(f-res,w[i])); w[i] -= temp; w[i^1] += temp; res += temp; if(res == f)return res; } } return res; } long long MCMF() { while(spfa())dfs(S,inf); return ans; } }mcmf; int a[2005]; int main() { int N=read(); for(int i=1;i<=N;i++){ a[i]=read(); } int p=read(),m=read(),f=read(),n=read(),s=read(); int S=0,T=N+N+1; mcmf.init(S,T); for(int i=1;i<=N;++i){ mcmf.add(S,i,a[i],0); mcmf.add(i+N,T,a[i],0); mcmf.add(S,i+N,1e9,p); if(i+1<=N) mcmf.add(i,i+1,1e9,0); if(i+m<=N) mcmf.add(i,i+N+m,1e9,f); if(i+n<=N) mcmf.add(i,i+N+n,1e9,s); } printf("%lld\n",mcmf.MCMF()); return 0; }