POJ2516 Minimum Cost(K次费用流)
2016-03-01 22:18
357 查看
链接:http://poj.org/problem?id=2516
题意太麻烦了,看懂题意之后就很简单了。。。不解释题意了。。。
思路:事先判断一下物品够不够。然后对每个物品建图跑费用流。建图的时候要小心,容易写错。
直接上代码吧
题意太麻烦了,看懂题意之后就很简单了。。。不解释题意了。。。
思路:事先判断一下物品够不够。然后对每个物品建图跑费用流。建图的时候要小心,容易写错。
直接上代码吧
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<map> #include<iostream> #include<vector> #include<cstdlib> #include<cmath> #include<stack> #include<cctype> #include<set> #include<ctime> #include<cassert> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int INF=1e9+7; #define MP make_pair #define PB push_back struct node{ int cap,cost; }G[110][110]; int n,m,k,st,ed,need[55][55],save[55][55],pic[55][55][55]; int d[110],pre[110],flow[110]; bool vis[110]; void input(){ for(int i=1;i<=n;i++){ for(int j=1;j<=k;j++){ scanf("%d",&need[i][j]);//need [k] } } for(int i=1;i<=m;i++){ for(int j=1;j<=k;j++){ scanf("%d",&save[i][j]);//save[m][k] } } for(int w=1;w<=k;w++){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&pic[w][i][j]);//pic[k] [m] } } } } bool check(){//判断一下是否不够 for(int w=1;w<=k;w++){ int sum=0; for(int i=1;i<=m;i++){ sum+=save[i][w]; } for(int i=1;i<=n;i++){ sum-=need[i][w]; } if(sum<0)return false; } return true; } void build(int w){//对每一个物品建图 memset(G,0,sizeof G); st=0;ed=n+m+1; //st->m cap:save[m][w] cost:0 //n->ed cap:need [w] cost:0 for(int i=1;i<=n;i++){ G[i+m][ed].cap=need[i][w]; } for(int j=1;j<=m;j++){ G[st][j].cap=save[j][w]; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ G[j][i+m].cap=save[j][w]; G[j][i+m].cost=pic[w][i][j]; G[i+m][j].cost=-pic[w][i][j]; } } } bool spfa(int &ff,int &ans){ queue<int> Q; Q.push(st); fill(d,d+ed+1,INF); d[st]=0;vis[st]=true;flow[st]=INF;pre[st]=-1; while(!Q.empty()){ int s=Q.front();Q.pop(); vis[s]=false; for(int i=1;i<=ed;i++){ if(G[s][i].cap>0&&d[i]>d[s]+G[s][i].cost){ d[i]=d[s]+G[s][i].cost; pre[i]=s; flow[i]=min(flow[s],G[s][i].cap); if(!vis[i]){ vis[i]=true;Q.push(i); } } } } if(d[ed]==INF)return false; ff+=flow[ed];ans+=flow[ed]*d[ed]; int now=ed; while(now!=st){ G[pre[now]][now].cap-=flow[ed]; G[now][pre[now]].cap+=flow[ed]; now=pre[now]; } return true; } int main() { // freopen("D://input.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&k)!=EOF&&n&&m&&k){ input(); if(!check()){printf("-1\n");continue;} int ff=0,ans=0; for(int w=1;w<=k;w++){ build(w); while(spfa(ff,ans));//printf("%d %d\n",ff,ans); } printf("%d\n",ans); } return 0; }
相关文章推荐
- Android自定义控件
- 统计你的手机号码中出现次数最多的数字,并打印出此数字及其出现次数
- 内存管理
- 多态的理解
- AngularJS图片上传功能的实现
- 无线智能小车(一)
- 快速幂
- Linux System Programming读书笔记之deamon进程
- C++工作现在需求怎么样,如何应对
- Android中Notification的使用
- TCP/IP状态详解
- Intellij idea 15破解
- HDU 1518 Square 搜索
- PAT-A1061 Dating (20)(模拟)
- C++工作现在需求怎么样,如何应对
- TypeScript 中的 "=>" 真的很好用!!!
- 正则表达式
- 认识 sun.misc.Unsafe
- 括号配对问题
- java单例模式