题目描述 Description
假设以最美观的方式布置花店的橱窗,有F束花,V个花瓶,我们用美学值(一个整数)表示每束花放入每个花瓶所产生的美学效果。为了取得最佳的美学效果,必须使花的摆放取得最大的美学值。
输入描述 Input Description
第一行为两个整数F,V(F<=V<=100)
接下来F行每行V个整数,第i行第j个数表示第i束花放入第j个花瓶的美学值。
输出描述 Output Description
一个整数,即最大美学值。
样例输入 Sample Input
2 2
10 0
5 2
样例输出 Sample Output
12
一道挺裸的题目吧
跑了费用流,然后单路增广
em.......
数据中有负权边
所以注意spfa前dis数组初始化为-inf(为了这个调了很久TAT)
然后建边之后一定要调试!一定要调试!一定要调试!(重要的事说三遍)
看你建的边对不对
要不等你整个码完了很难发现是哪里错了
还有const 的int 要注意区分,不小心弄错了又调了很久
最后,反向弧要开两倍!!!
#include<cstdio> #include<cstring> const int M=103*103*2,N=210,len=10000; struct node { int from,to,next,v,c; }e[M]; int first[N]; int s=0,t; int dis[N],bo[N],qu[len]; int from[N]; int ans=0; bool spfa() { for(int i=1;i<=t;i++) dis[i]=1e8*-1; dis[0]=0; bo[0]=1; qu[1]=0; int i=1,j=2; while(i!=j) { int r=qu[i++];if(i==len) i=1;bo[r]=0; for(int k=first[r];k;k=e[k].next) { if(e[k].v>0&&dis[e[k].to]<dis[r]+e[k].c) { dis[e[k].to]=dis[r]+e[k].c; from[e[k].to]=k; if(!bo[e[k].to]) { if(dis[e[k].to]>dis[qu[i]]) { i--;if(i<1) i=len-1; qu[i]=e[k].to; } else { qu[j++]=e[k].to;if(j==len) j=1; } bo[e[k].to]=1; } } } } if(dis[t]<0) return 0; return 1; } void fa() { int min=1e8; for(int k=from[t];k;k=from[e[k].from]) min=min<e[k].v?min:e[k].v; for(int k=from[t];k;k=from[e[k].from]) { e[k].v-=min;e[k^1].v+=min; ans+=e[k].c*min; } } int main() { int f,n,cnt=1; scanf("%d %d",&f,&n); t=f+n+1; int k; for(int i=1;i<=f;i++) {//没有写成函数,略丑TAT e[++cnt].to=i;e[cnt].from=s;e[cnt].v=1;e[cnt].c=0;e[cnt].next=first[s];first[s]=cnt; e[++cnt].to=s;e[cnt].from=i;e[cnt].v=0;e[cnt].c=0;e[cnt].next=first[i];first[i]=cnt; for(int j=1;j<=n;j++) { scanf("%d",&k); e[++cnt].to=f+j;e[cnt].v=1;e[cnt].from=i;e[cnt].c=k;e[cnt].next=first[i];first[i]=cnt; e[++cnt].to=i;e[cnt].v=0;e[cnt].from=f+j;e[cnt].c=-k;e[cnt].next=first[f+j];first[f+j]=cnt; if(i==1) { e[++cnt].to=t;e[cnt].from=f+j;e[cnt].v=1;e[cnt].c=0;e[cnt].next=first[f+j];first[f+j]=cnt; e[++cnt].to=f+j;e[cnt].from=t;e[cnt].v=0;e[cnt].c=0;e[cnt].next=first[t];first[t]=cnt; } } } while(spfa()) fa(); printf("%d",ans); return 0; }