建边有技巧啊,要拆点。
网络流建边的核心规律就是多做题一定是从源点到汇点,根据此构建模型即可。
\(dinic\) 实现最小费用流
/* @Date : 2019-07-16 11:10:42 @Author : Adscn (adscn@qq.com) @Link : https://www.cnblogs.com/LLCSBlog */ #include<bits/stdc++.h> using namespace std; #define IL inline #define RG register #define gi getint() #define gc getchar() #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) IL int getint() { RG int xi=0; RG char ch=gc; bool f=0; while(ch<'0'|ch>'9')ch=='-'?f=1:f,ch=gc; while(ch>='0'&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc; return f?-xi:xi; } template<typename T> IL void pi(T k,char ch=0) { if(k<0)k=-k,putchar('-'); if(k>=10)pi(k/10,0); putchar(k%10+'0'); if(ch)putchar(ch); } const int inf=2147483647,N=2007; int S=0,T; struct edge{int v,nxt,flow,w;}e[N<<2]; int head[N<<1],cnt; int cur[N<<1]; inline void add(int u,int v,int flow,int cost){e[cnt]=(edge){v,head[u],flow,cost};head[u]=cnt++;} inline void link(int u,int v,int flow,int cost){add(u,v,flow,cost);add(v,u,0,-cost);} int dis[N<<1]; bool vis[N<<1]; int spfa() { memset(dis,127,sizeof dis); memset(vis,0,sizeof vis); static int Q[N<<1],l,r; dis[Q[l=r=0]=S]=0; while(l<=r) { int p=Q[l++]; vis[p]=0; for(int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[p]+e[i].w&&e[i].flow) { dis[v]=dis[p]+e[i].w; if(!vis[v])Q[++r]=v,vis[v]=1; } } } return dis[T]<1e9; } long long ans; int dfs(int p,int restflow) { if(p==T||restflow==0)return restflow; int sumflow=0; vis[p]=1; for(int &i=cur[p],flow;(~i)&&restflow;i=e[i].nxt) { int v=e[i].v; if(vis[v]==0&&e[i].flow&&dis[v]==dis[p]+e[i].w&&(flow=dfs(v,min(restflow,e[i].flow)))) { sumflow+=flow,restflow-=flow; e[i].flow-=flow,e[i^1].flow+=flow; ans+=1ll*flow*e[i].w; } } vis[p]=0; return sumflow; } void dinic(){while(spfa())memcpy(cur,head,sizeof head),dfs(S,inf);} int main(void) { #ifndef ONLINE_JUDGE File("file"); #endif int n=gi;T=n*2+1; memset(head,-1,sizeof head); for(int i=1;i<=n;++i) { int x=gi; link(S,i,x,0); link(i+n,T,x,0); } int newcost=gi,fastday=gi,fastcost=gi,slowday=gi,slowcost=gi; for(int i=1;i<=n;++i) { if(i<n)link(i,i+1,inf,0); if(i+slowday<=n)link(i,i+n+slowday,inf,slowcost); if(i+fastday<=n)link(i,i+n+fastday,inf,fastcost); link(S,i+n,inf,newcost); } dinic(); pi(ans); return 0; }