首页 > 其他分享 >越流越贵(最小费用最大流)

越流越贵(最小费用最大流)

时间:2024-08-22 11:27:18浏览次数:9  
标签:pre 费用 idx int flow 最小 leq 越流越

题目描述
给定一个\(n\)个点\(m\)条边的费用流图,源点为\(1\),汇点为\(n\),求最小费用最大流。

如果第\(i\)条边流量为\(f\),则第\(i\)条边的费用为\(f^2\),注意每条边的流量必须是整数。
输入
第一行包含一个正整数\(T(1\leq T\leq 10)\),表示测试数据的组数。

每组数据第一行包含两个正整数\(n,m(1\leq n\leq 50,1\leq m\leq 500)\)。

接下来\(m\)行,每行三个正整数\(a[i],b[i],c[i](1\leq a[i],b[i]\leq n,a[i]\neq b[i],1\leq c[i]\leq 10)\),表示一条起点是\(a[i]\),终点是\(b[i]\)的边,容量上限是\(c[i]\)。

注意到c[i]很小,同时损失函数是凸函数,考虑拆边,注意拆边的流量应该为1

#include<bits/stdc++.h>
using namespace std;
const int N = 1000,M = 100000,INF = 0x3f3f3f3f;
int h[N],e[M],ne[M],f[M],w[M],idx;
int d[N],flow[N],pre[N];
bool st[N];
queue<int> q;
//a->b一条流量为c,费用为d的边
void add(int a,int b,int c,int d){
   e[idx] =b,f[idx] =c,w[idx]= d,ne[idx]= h[a],h[a]= idx++;
   e[idx] =a,f[idx] =0,w[idx]=-d,ne[idx]= h[b],h[b] = idx++;
}
bool spfa(int s,int t){
    memset(d,0x3f,sizeof d);
	memset(flow,0,sizeof flow);
	d[s] = 0,flow[s] =0x3f3f3f3f;
	q.push(s);

	while(q.size())
	{
	int u = q.front();
	q.pop();
	st[u]= 0;
 
	for(int i = h[u];i!=-1;i = ne[i])
	{
		int v =e[i];
	
		if(f[i] && d[v] > d[u]+ w[i])
		{
			d[v] =d[u] + w[i];
			pre[v] =i;
			flow[v]= min(f[i],flow[u]);

			if(!st[v])
			{
				q.push(v);
				st[v]= 1;
			}
		}
	}
	}
	return flow[t] > 0;
}
pair<int,int> EK(int s,int t){
	int maxflow= 0,mincost =0;
	while(spfa(s,t)){
	int r = flow[t];
	maxflow+= r,mincost += r* d[t];

	for(int i = t;i !=s;i = e[pre[i]^ 1]){
	f[pre[i]]-=r;
	f[pre[i]^ 1] += r;
	}
 	}	
    return make_pair(maxflow,mincost);
	}
int n,m;

void solve()
{
	memset(h,-1,sizeof h);
	cin>>n>>m;
	int s = 1, t = n;
	//由于损耗的费用不是常数,同时x^2是一个凸函数
	//可以拆边,把费用拆开
	for(int i=1;i<=m;++i)
	{
		int u,v,f;
		cin>>u>>v>>f;
		for(int j=1;j<=f;++j)
		{
			//注意此处拆边的时候流量应该变为1
			add(u,v,1,j*j-(j-1)*(j-1));
		}
	}
	auto [maxflow,mincost] = EK(s,t);
	cout<<maxflow<<' '<<mincost<<'\n';
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

标签:pre,费用,idx,int,flow,最小,leq,越流越
From: https://www.cnblogs.com/ruoye123456/p/18373478

相关文章

  • K取方格数(最大费用流)
    题目描述给定\(n\timesm\)的方格\(a[1..n][1..m]\),每个格子有一个数。从\((1,1)\)出发走到\((n,m)\)一共不超过\(K\)次,只能往右往下走,走过的位置的数会变成\(0\)。问经过的位置的数字之和的最大值是多少。输入第一行包含一个正整数\(T(1\leqT\leq10)\),表示测试数据的组数......
  • Mat的最大值、最小值
    学OpenCV================================================这里的行列对应y和x。 ================================================1#include<iostream>23#include<opencv2/opencv.hpp>4#include<opencv2/core/utils/logger.hpp>567......
  • 偷宝石(最大流转化最小割)
    题目描述\(n\)个宝石,\(m\)个保安,每个保安监控着一些宝石。偷走第\(i\)个宝石能卖\(a[i]\)元,贿赂第\(i\)个保安需要\(b[i]\)元,你能偷走某个宝石当且仅当监控它的保安都被你贿赂过了。问你的最大收益是多少。输入第一行包含一个正整数\(T(1\leqT\leq10)\),表示测试数据的组数......
  • 最小割
    题目描述给定\(n\)个点\(m\)条边的有向图,删掉第\(i\)条边的代价为\(c[i]\)。请删掉代价之和最少的边,使得从\(1\)号点出发到达不了\(n\)号点。输入第一行包含一个正整数\(T(1\leqT\leq10)\),表示测试数据的组数。每组数据第一行包含两个正整数\(n,m(1\leqn\leq50,1\leqm\l......
  • 模拟费用流
    模拟费用流是什么考虑一般的单路增广费用流流程,就是一直去寻找最小/最大费用增广路的过程。但是寻找一条增广路往往需要最短路算法,这造成了很大的时间开销。找到增广路的方式不唯一,可以通过别的手段去寻找增广路。在一些特殊网络中可以获得更加优秀的时间复杂度。QOJ7185题目......
  • C++图笔记(三)有向无环图(及最小生成树(略))以及剩下的排序
    目录一,定义:1,有向无环图 2,拓朴排序 1,每个顶点出现且仅仅出现一次。 2,若存在一条从顶点A到顶点B的路径,那么在序列中顶点A出现在顶点B的前面。二,DAG的性质性质1.  从任意一个起点进行dfs,必不会陷入死循环。性质2.  入度为0的点信息确定,删掉入度为0的点......
  • 威高血净偏高的关联交易:销售费用率远高同行,现金流转负
    《港湾商业观察》施子夫 王璐日前,山东威高血液净化制品股份有限公司(以下简称,威高血净)针对首轮审核问询函进行了回复。威高血净的上市梦由来已久。早在2022年6月公司就递表港交所,其后无果,2023年12月30日公司又递表上交所主板,保荐机构为华泰联合证券。威高血净成立于2004......
  • 阿里云ACP的三种报名与对应题库获取方式的详细说明(按费用排序)
    文章目录前言方式一、官方途径(较为昂贵)考试资格获取官方视频教程获取方式总结方式二、报名机构(价格适中,考取速度快)推荐机构大概费用机构报名方式机构报名后所携带的内容或者说对于其他方法有什么优势总结方式三、闲鱼(最便宜,但题库有风险)考试资格获取题库获取总......
  • 【代码随想录训练营第42期 Day32打卡 - 从零开始动态规划 - LeetCode 509. 斐波那契数
    目录一、做题心得二、动规五步走三、题目与题解题目一:509.斐波那契数题目链接题解1:记忆性递归 题解2:动态规划题目二:70.爬楼梯 题目链接题解:动态规划题目三:746.使用最小花费爬楼梯题目链接题解:动态规划三、小结一、做题心得今天开始动态规划章节的第一......
  • 【数据结构与算法】如何构建最小堆
    最小堆的定义最小堆,作为一种独特且重要的数据结构,它是一种特殊的二叉树。在这种二叉树中,有一个关键的规则:每一个父节点所存储的值,都必然小于或者等于其对应的子节点的值。这一规则确保了根节点总是承载着整个堆中的最小数值。例如,下面这样一个简单的结构就是最小堆:1......