您的位置:首页 > 其它

POJ 2516 Minimum Cost [最小费用最大流]

2016-04-20 18:24 309 查看
题意略;

思路:

这题比较坑的地方是把每种货物单独建图分开算就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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: