最小费用流
来源:互联网 发布:windows curl 安装 编辑:程序博客网 时间:2024/04/29 04:52
单向图
#include<cstdio>//每次找费用的最短路,更新残留网络图直到找不到最短路为止#include<cstring>//最大费用 权值取负值 结果取负值#include<iostream>#include<algorithm>#include<queue>using namespace std;const int inf=0x3f3f3f3f;struct Node{ int u,v,w,cost,next;}node[1001000];int head[1001000],cont,sumflow;int vis[101000],dist[101000];int pre[101000];void init(){ cont=0; sumflow=0; memset(head,-1,sizeof(head));}void add(int u,int v,int w,int cost)//建图{ int i; for(i=head[u]; i!=-1; i=node[i].next)//去重边 { if(node[i].v==v) { if(node[i].cost>cost)//更新重边的费用 node[i].cost=cost,node[i^1].cost=-cost; return ; } } node[cont].u=u,node[cont].v=v; node[cont].w=w,node[cont].cost=cost; node[cont].next=head[u],head[u]=cont++; node[cont].u=v,node[cont].v=u; node[cont].w=0,node[cont].cost=-cost;//反向边费用为负的 node[cont].next=head[v],head[v]=cont++;}int SPFA(int st,int ed)//寻找最短路{ queue<int> q; //memset(vis,0,sizeof(vis));//数组太大容易超时 //memset(pre,-1,sizeof(pre)); for(int i=0; i<=ed; i++) { dist[i]=inf; vis[i]=0; pre[i]=-1; } dist[st]=0; vis[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=node[i].next) { int v=node[i].v; if(node[i].w&&dist[v]>dist[u]+node[i].cost) { dist[v]=dist[u]+node[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(dist[ed]==inf) return 0;//找不到最短路 return 1;}int MCMF(int st,int ed){ int mincost=0,flow=0; while(SPFA(st,ed))//有最短路 更新残留网络 { int mins=inf; for(int i=pre[ed]; i!=-1; i=pre[node[i].u])//找到这条路径上的最小能更新的流量 mins=min(mins,node[i].w); for(int i=pre[ed]; i!=-1; i=pre[node[i].u])//更新流量 { node[i].w-=mins; node[i^1].w+=mins; } mincost+=dist[ed]*mins;//每次找到最短路后更新最小费用 flow+=mins;//更新最大流 } sumflow=flow;//最大流 return mincost;}int main(){ int ncase; scanf("%d",&ncase); while(ncase--) { init(); int n,m; scanf("%d%d",&n,&m); int st=0,ed=2*n+1; for(int i=1; i<=n; i++) { add(st,i,1,0); add(i+n,ed,1,0); } for(int i=0; i<m; i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b+n,1,c); } int ans=MCMF(st,ed);//最小费用最大流 printf("%d\n",ans); } return 0;}
题目链接请点这里
双向图
#include<cstdio>//每次找费用的最短路,更新残留网络图直到找不到最短路为止#include<cstring>//最大费用 权值取负值 结果取负值#include<iostream>#include<algorithm>#include<queue>using namespace std;const int inf=0x3f3f3f3f;struct Node{ int u,v,w,cost,next;}node[1001000];int head[1001000],cont,sumflow;int vis[101000],dist[101000];int pre[101000];void init(){ cont=0; sumflow=0; memset(head,-1,sizeof(head));}void add(int u,int v,int w,int cost)//建图{ int i; for(i=head[u]; i!=-1; i=node[i].next)//去重边 { if(node[i].v==v) { if(node[i].cost>cost)//更新重边的费用,有时是双向边 { //cost,-cost;//第二条边 node[i^2].cost=node[i].cost=cost,node[(i^1)^2].cost=node[i^1].cost=-cost;//第一条边 } return ; } } node[cont].u=u,node[cont].v=v; node[cont].w=w,node[cont].cost=cost; node[cont].next=head[u],head[u]=cont++; node[cont].u=v,node[cont].v=u; node[cont].w=0,node[cont].cost=-cost;//反向边费用为负的 node[cont].next=head[v],head[v]=cont++;}int SPFA(int st,int ed)//寻找最短路{ queue<int> q; //memset(vis,0,sizeof(vis));//数组太大容易超时 //memset(pre,-1,sizeof(pre)); for(int i=0; i<=ed; i++) { dist[i]=inf; vis[i]=0; pre[i]=-1; } dist[st]=0; vis[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=node[i].next) { int v=node[i].v; if(node[i].w&&dist[v]>dist[u]+node[i].cost) { dist[v]=dist[u]+node[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(dist[ed]==inf) return 0;//找不到最短路 return 1;}int MCMF(int st,int ed){ int mincost=0,flow=0; while(SPFA(st,ed))//有最短路 更新残留网络 { int mins=inf; for(int i=pre[ed]; i!=-1; i=pre[node[i].u])//找到这条路径上的最小能更新的流量 mins=min(mins,node[i].w); for(int i=pre[ed]; i!=-1; i=pre[node[i].u])//更新流量 { node[i].w-=mins; node[i^1].w+=mins; } mincost+=dist[ed]*mins;//每次找到最短路后更新最小费用 flow+=mins;//更新最大流 } sumflow=flow;//最大流 return mincost;}int main(){ int ncase,Z=0; scanf("%d",&ncase); while(ncase--) { init(); int n,m; scanf("%d%d",&n,&m); int st=0,ed=2*n+1; for(int i=1; i<=n; i++) { add(st,i,1,0); add(i+n,ed,1,0); } for(int i=0; i<m; i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c);//双向边 add(a,b+n,1,c); add(b,a+n,1,c); } int ans=MCMF(st,ed);//最小费用最大流 printf("Case %d: ",++Z); if(sumflow!=n) printf("NO\n"); else printf("%d\n",ans); } return 0;}
题目链接
0 0
- 最小费用最小流uva10746
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 最小费用流模版
- 【最小费用最大流】
- 最小费用流
- 最小费用最大流
- 最小费用最大流
- Intervals----最小费用流
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- hdu1853 最小费用流
- hdu1533 最小费用流
- hdu3667 最小费用流
- iOS Sqlite3 数据库的升级
- EventBus使用
- DF计算例子
- 在做javaWeb项目时,每次修改完servlet,tomcat自动重启项目,设置项目自动的热加载
- Coursera Machine Learning 第八周 quiz Principal Component Analysis
- 最小费用流
- 解决Mysql导入csv中空值变为0的问题:导入数据时设定格式
- Android四大组件之一,内容提供器Content Provider详解
- ListView 嵌套在 ScrollView中、Lv加载完数据之后Sv会滚动到Lv的最后一个item
- python中的map()函数
- Balsamiq Mockups 3.5.5 for Windows / Mac 简体中文汉化 最佳原型设计工具之一
- C++动态配置的实现
- linux下zip加密压缩文件
- Linux开发工具的使用(一)