POJ 2516 Minimum Cost [最小费用最大流]
2016-04-20 18:24
309 查看
题意略;
思路:
这题比较坑的地方是把每种货物单独建图分开算就ok了。
思路:
这题比较坑的地方是把每种货物单独建图分开算就ok了。
#include<stdio.h> #include<queue> #define MAXN 500 #define MAXM 10002*4 #define INF 10000000 using namespace std; //起点编号必须最小,终点编号必须最大 bool vis[MAXN]; //spfa中记录是否在队列里边 char pho[105][105]; int max_flow; struct point{ int x,y; }man[105],house[105]; struct edge{ edge *next,*op; //op是指向反向边 int t,c,v; //t下一个点编号,c容量,v权值 }ES[MAXM],*V[MAXN]; //ES边静态邻接表,V点的编号 struct st{ int num[55]; }; st from[55],to[55]; int N,M,S,T,EC=-1; //S源点最小,T汇点最大,EC当前边数 int demond[MAXN],sp[MAXN],prev[MAXN]; //spSPFA中记录距离,prev记录上一个点路径 edge *path[MAXN]; //与prev同步记录,记录到上一条边 void addedge(int a,int b,int v,int c=INF){ //printf("* %d %d %d %d\n",a,b,v,c); edge e1={V[a],0,b,c,v},e2={V[b],0,a,0,-v}; ES[++EC]=e1;V[a]=&ES[EC]; ES[++EC]=e2;V[b]=&ES[EC]; V[a]->op=V[b];V[b]->op=V[a]; } bool SPFA(){ int u,v; for(u=S;u<=T;u++){ sp[u]=INF; } queue<int>q; prev[S]=-1; q.push(S); sp[S]=0; vis[S]=1; while(!q.empty()){ u=q.front(); vis[u]=0; q.pop(); for(edge *k=V[u];k;k=k->next){ v=k->t; if(k->c>0&&sp[u]+k->v<sp[v]){ sp[v]=sp[u]+k->v; prev[v]=u; path[v]=k; if(vis[v]==0){ vis[v]=1; q.push(v); } } } } return sp[T]!=INF; } int argument(){ int i,cost=INF,flow=0; edge *e; for(i=T;prev[i]!=-1;i=prev[i]){ e=path[i]; if(e->c<cost)cost=e->c; } max_flow+=cost; for(int i=T;prev[i]!=-1;i=prev[i]){ e=path[i]; e->c-=cost;e->op->c+=cost; flow+=e->v*cost; } return flow; } int maxcostflow(){ int Flow=0; while(SPFA()){ Flow+=argument(); } return Flow; } bool init(){ int n,m,k; bool ok=1; long long ans=0; scanf("%d%d%d",&n,&m,&k); if(n==0&&m==0&&k==0)return 0; for(int i=0;i<n;i++){ for(int j=0;j<k;j++){ scanf("%d",&to[i].num[j]); } } for(int i=0;i<m;i++){ for(int j=0;j<k;j++){ scanf("%d",&from[i].num[j]); } } for(int i=0;i<k;i++){ EC=-1; max_flow=0; for(int j=0;j<=MAXN;j++){ V[j]=NULL; } for(int j=0;j<n;j++){ for(int w=0;w<m;w++){ int tmp; scanf("%d",&tmp); addedge(w+1,m+j+1,tmp); } } for(int j=0;j<m;j++){ addedge(0,j+1,0,from[j].num[i]); } int sum=0; for(int j=0;j<n;j++){ addedge(j+1+m,m+n+1,0,to[j].num[i]); sum+=to[j].num[i]; } S=0;T=n+m+1; ans+=maxcostflow(); if(max_flow!=sum)ok=0; } if(!ok)ans=-1; printf("%I64d\n",ans); return 1; } int main(){ while(init()); return 0; }
相关文章推荐
- Nginx技巧:灵活的server_name,Nginx配置一个服务器多个站点 和 一个站点多个二级域名
- Android ListView 使用相关技巧
- 聪明的kk
- Java设计模式系列之命令模式
- A20平台固件解包打包
- React Native中的事件
- [Module]Struct Module学习(待续)
- Program2_1009
- lintcode之 合并排序数组 II
- NJUST 1926 琪露诺的算术教室 (解方程 大数)
- Java中访问权限的等级
- 数论--Lucas Theorem
- 关于Curator学习过程问题
- JavaScript的类型转换(2)
- Android实例-获取程序版本号(XE10+小米2)
- 团队作业(三)解答
- Linux进阶之bash编程(流程控制-for循环)
- java流总结(1) 字节流
- ffmpeg中的pcm格式
- sqlserver游标使用误区