首页 > 代码库 > 最小费用最大流
最小费用最大流
我最近学习了最小费用最大流;
我还是简略谈谈最小费用最大流吧
什么是最小费用最大流?
我们可以把最小费用看做是最短路;
简单吧!!!!
也就是一条边有两个权值;
一个为边权,另一个为流值;
什么是最大流?
当我们求出了最小费用时;
实质上求出了最短路;
而此时最大流为最短路上的每一条边的流值的最小值;
此时最小费用最大流为最短路的长度*最大流;
怎么求最小费用?
很简单!!!!!
我们就是求单源最短路径;
我们可以写spfa Dijkstra Bellman-Ford floyd(这个作死)
我们每次求完最小费用最大流时;
我们应把最短路上所有边反向;
使反向的边的边权为它所对应的正向边权的相反数;
而正向边的流值应减去最大流;反向边的流值应加上最大流(流值最开始为0);
哦!别忘了将正向边的流值为0的边的权值该为无穷大;(防止走重复的最短路);
我们一直这样操作,直到起点连不到终点,在退出,每次的最小费用最大流加起来则为总的最小费用最大流;
给作参考:
#include<stdio.h>
#include<stdlib.h>#define max1 1000000000
int a[1000][1000],f[1000][1000];
int d[1000];//d表示某特定边距离
int p[1000],h[1000];//p表示永久边距离
int i,j,sum=0,ans=0;
int m;//m代表边数
int n,g;//n代表点数
int dfs(int k,int h1)
{
int j;
if(f[h[k]][k]<h1 && f[h[k]][k]!=0)h1=f[h[k]][k];
a[k][h[k]]=-a[h[k]][k];
//printf("%d ",h[k]);
if(h[k]==1)return h1;
j=dfs(h[k],h1);
return j;
}
int cherk(int t,int k)
{
f[h[t]][t]-=k;f[t][h[t]]+=k;
if(f[h[t]][t]==0)a[h[t]][t]=max1;
if(h[t]==1)return 0;
cherk(h[t],k);
return 0;
}
int main()
{
//freopen("dj.in","r",stdin);
//freopen("dj.out","w",stdout);
scanf("%d%d",&n,&m);
int min1,x,y,z,w,k,o=0;
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&z,&w);//z是流,w是费用;
a[x][y]=w;f[x][y]=z;
//a[y][x]=-w;
f[y][x]=0;
}
for(o=1;;o++)
{
k=0;
for(i=1;i<=n;i++)
d[i]=max1;
d[1]=0;
for(i=1;i<=n;i++)
{h[i]=0;p[i]=0;}
for(i=1;i<=n;i++)
{
min1=max1;
for(j=1;j<=n;j++)
if(!p[j]&&d[j]<min1)
{
min1=d[j];
k=j;
}
p[k]=1;
for(j=1;j<=n;j++)
if(a[k][j]!=0&&!p[j]&&d[j]>d[k]+a[k][j])
{d[j]=d[k]+a[k][j];h[j]=k;}
}
if(d[n]>=max1)
break;
k=548566;
//for(i=1;i<=n;i++)
// printf("%d ",h[i]);
//printf("%d",&h[i]);
k=dfs(n,k);
cherk(n,k);
sum+=k*d[n];ans+=k;
//printf("%d %d\n",k,d[n]);
}
printf("%d %d",ans,sum);
//for(i=1;i<=n;i++)
// printf("%d ",d[i]);
//fclose(stdin);
//fclose(stdout);
//while(1);
return 0;
}
最小费用最大流
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。