【网络流】【BZOJ1221】【HNOI2001】软件开发
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1221
题意:你有3种方法进行对毛巾的处理,不同的处理方法有不同的cost,问你要如何规划才可以使得总花费最低。
解题思路:我们对每个点进行拆点,分为用过的毛巾和没用过的,这样就可以较为简单的连边,然后跑个最小费用最大流即可。
AC代码:
#include<stdio.h> #include<string.h> #define inf 0x7fffffff #define min(a,b) (a<b?a:b) struct zxy{int to,next,c,v;}edge[40100]; int n,e,cnt=1,head[2005],dis[2005],que[10001],pre[2005],fc,ta,tb,fa,fb; bool vis[2005]; inline int in(){ int x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } inline void ins(int x,int y,int v,int l){ edge[++cnt].to=y,edge[cnt].next=head[x],edge[cnt].v=v,edge[cnt].c=l,head[x]=cnt; edge[++cnt].to=x,edge[cnt].next=head[y],edge[cnt].v=0,edge[cnt].c=l*(-1),head[y]=cnt; } inline bool SPFA(int s,int e){ for (register int i=s; i<=e; ++i) dis[i]=inf/3; int h=0,t=1; que[1]=s; dis[s]=0;vis[s]=1; do{ int w=que[++h]; for (register int i=head[w]; i; i=edge[i].next) if (dis[w]+edge[i].c<dis[edge[i].to]&&edge[i].v){ int v=edge[i].to;pre[v]=i; dis[v]=dis[w]+edge[i].c; if (!vis[v]){ vis[v]=1; if (dis[v]<dis[que[h+1]])que[h--]=v; else que[++t]=v; } } vis[w]=0; }while(h<t); return dis[e]!=inf/3; } int cost_flow(int s,int t){ int cost=0; while(SPFA(s,t)){ int mi=inf; for (register int i=t; i; i=edge[pre[i]^1].to) mi=min(mi,edge[pre[i]].v); for (register int i=t; i; i=edge[pre[i]^1].to) edge[pre[i]].v-=mi,edge[pre[i]^1].v+=mi; cost+=dis[t]*mi; } return cost; } void init(){ n=in(),ta=in(),tb=in(),fc=in(),fa=in(),fb=in(); for (int i=1; i<=n; ++i){ register int x=in(); ins(0,n+i,inf,fc); ins(0,i,x,0); ins(n+i,2*n+1,x,0); if(i<n) ins(i,i+1,inf,0); if(i+ta<n) ins(i,i+ta+n+1,inf,fa); if(i+tb<n) ins(i,i+tb+n+1,inf,fb); } } int main(){ init(); printf("%d",cost_flow(0,2*n+1)); }