最小费用最大流(模板)

来源:互联网 发布:手机管理网络的软件 编辑:程序博客网 时间:2024/05/22 23:13
#define MAXN 1005#define INF 2000000000int source,sink; //源点 汇点 struct tree{int from,to,flow,worth,next; //结点,流量,费用,链表 tree(){}tree(int fr,int ro,int fl,int wo,int ne){from=fr,to=ro,flow=fl,worth=wo,next=ne;}}e[MAXN*MAXN];int g[MAXN]; // 建立链表int num;  //边数void init() //初始化{memset(g,0,sizeof(g));num=1;}void addtree(int from,int to,int flow,int worth)  //建图 {e[++num]=tree(from,to,flow,worth,g[from]);g[from]=num;e[++num]=tree(to,from,0,-worth,g[to]);    //反向弧 g[to]=num;}bool visque[MAXN]; //查看是否入队int dis[MAXN]; //最小距离int pre[MAXN],prx[MAXN]; //记录路线用于更新残量图 queue<int>q;int bfs() //寻找最短路{while(!q.empty()) q.pop(); //初始化队列for(int i=0;i<=MAXN;i++) dis[i]=INF; //初始化距离 q.push(source); //源点入队dis[source]=0;visque[source]=true;while(!q.empty()){int u=q.front();q.pop();for(int i=g[u];i;i=e[i].next){if(e[i].flow>0&&dis[u]+e[i].worth<dis[e[i].to]) //更新最短路 {dis[e[i].to]=dis[u]+e[i].worth;pre[e[i].to]=u;prx[e[i].to]=i;if(!visque[e[i].to]){visque[e[i].to]=true;q.push(e[i].to);}}}visque[u]=false; //前面已经让u出队了所以这里要写一下 } return dis[sink]!=INF; //判断是否可以到达汇点 } int dfs(){int u=sink;int ans=INF;while(u!=source) //找当前路中的最小流量 {if(e[prx[u]].flow<ans) ans=e[prx[u]].flow;u=pre[u];}u=sink;while(u!=source) //更新残量图 {e[prx[u]].flow-=ans;e[prx[u]^1].flow+=ans;u=pre[u];}return ans*dis[sink];}int solve(){int cur=0;int ans=0;while(bfs()){cur+=dfs();if(cur>ans) ans=cur;} return ans;}

原创粉丝点击