Remember the A La Mode
Posted kstranger
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Remember the A La Mode相关的知识,希望对你有一定的参考价值。
这道题是一个裸网络流
不过要注意以下几点:
1、题目中的输入是浮点数(有个毒瘤,我自己写的网络流结果tle,看了大佬代码把浮点数整形化就过了)
2、这个题目是练习超级源点和超级汇点的不错的题
3、求最大的网络流就把cost取反求最小值就行
以下是代码
//抽象为一个图源点和汇点是无穷的边 //超级源点和超级汇点的连边容量来约束饼干的个数和冰淇淋的个数 //每个边的权重是这两个种类合并的收益 #include <iostream> #include <cstring> #include <queue> using namespace std; const int N =10010; const int INF = 0x3f3f3f3f; // const int MAX=110; int vi[N],pre[N],numsp[N],numsl[N]; int pos[N][N]; int dis[N]; int maxcost=0,mincost=0; int p,l; struct edg{ int from,to; int cap; int flow; int cost; }edgs[N]; int h[N],ne[N],idx=0; void add(int a,int b,int cap,int w){ edgs[idx]={a,b,cap,0,w}; ne[idx]=h[a]; h[a]=idx++; } bool spfa(int s,int t){ memset(pre,-1,sizeof pre); memset(vi,0,sizeof vi); memset(dis,0x3f,sizeof dis); queue<int> q; q.push(s); vi[s]=1; dis[s]=0; pre[s]=-1; while(!q.empty()){ int tem=q.front(); q.pop(); vi[tem]=0; for(int i=h[tem];~i;i=ne[i]){ int to=edgs[i].to; if(edgs[i].cap>0&&dis[to]>dis[tem]+edgs[i].cost){ dis[to]=dis[tem]+edgs[i].cost; pre[to]=i; if(!vi[to]){ q.push(to); vi[to]=1; } } } } return pre[t]!=-1; } void mcmf(int s,int t){ while(spfa(s,t)){ int now=t; int nowflow=INF; // for(int i=pre[t];i!=-1;i=pre[edgs[i].from]){ // nowflow=min(nowflow,edgs[i].cap); // } while(now!=s){ nowflow=min(nowflow,edgs[pre[now]].cap); now=edgs[pre[now]].from; } // // cout<<nowflow<<endl; // cout<<mincost<<endl; // for(int i=pre[t];i!=-1;i=pre[edgs[i].from]){ // edgs[i].cap-=nowflow; // edgs[i^1].cap+=nowflow; // } now=t; mincost+=nowflow*dis[t]; while(now!=s){ // edgs[pre[now]].flow=nowflow; edgs[pre[now]].cap-=nowflow; edgs[pre[now]^1].cap+=nowflow; now=edgs[pre[now]].from; } } } int main(){ cin>>p>>l; for(int i=1;i<=p;i++)cin>>numsp[i]; for(int i=1;i<=l;i++)cin>>numsl[i]; memset(h,-1,sizeof h); for(int i=1;i<=p;i++){ for(int j=p+1;j<=p+l;j++){ double cost; cin>>cost; if(cost>0){ cost=cost*100+0.5; cost=(int)cost; pos[i][j]=cost; add(i,j,INF,-cost); add(j,i,0,cost); } else{ pos[i][j]=0; } } } for(int i=1; i <= p;i++){ add(0,i,numsp[i],0); add(i,0,0,0); } for(int i=p+1;i <= p+l;i++){ add(i,p+l+1,numsl[i-p],0); add(p+l+1,i,0,0); } // for(int i=h[1];~i;i=ne[i]){ // cout<<edgs[i].to<<" "<<edgs[i].cost<<endl; // } mcmf(0,p+l+1); maxcost=(-mincost); mincost=0; idx=0; memset(h,-1,sizeof h); for(int i=1;i<=p;i++){ for(int j=p+1;j<=p+l;j++){ if(pos[i][j]>0){ add(i,j,INF,pos[i][j]); add(j,i,0,-pos[i][j]); } } } for(int i=1; i <= p;i++){ add(0,i,numsp[i],0); add(i,0,0,0); } for(int i=p+1;i <= p+l;i++){ add(i,p+l+1,numsl[i-p],0); add(p+l+1,i,0,0); } mcmf(0,p+l+1); printf("%.2lf to %.2lf",mincost/100.0,maxcost/100.0); // cout<<mincost/100.0<<" to "<<maxcost/100.0<<endl; }
以上是关于Remember the A La Mode的主要内容,如果未能解决你的问题,请参考以下文章
LA 3942 && UVa 1401 Remember the Word (Trie + DP)