首页 > 编程语言 >Primal-Dual 原始对偶算法

Primal-Dual 原始对偶算法

时间:2023-11-09 20:01:25浏览次数:38  
标签:typedef now 对偶 int Primal flow Dual include dis

想把 spfa 换成 dij,用 Johnson 里面的技巧,给予每个点一个势能 \(h_u\),边 \((u,v,w)\) 的新边权为 \(w+h_u-h_v\),为了保证其 \(\geq 0\) 以源点为最短路跑最短路后赋值 \(h_u\gets d_u\) 即可。

增广之后会加入反向边,考虑怎么更新势能。首先一条边的反向边被加入,其满足什么条件,然后推推式子(这里令 \(d'\) 为以 \(h\) 作为势能的最短路):

\(d'_u+w_{u,v}+h_u-h_v=d'v\)

将同类型的合并:

\((d'_u+h_u)-(d'_v+h_v)+w_{u,v}=0\)

有 \(w_{u,v}=-w_{v,u}\) 所以 \((d'_u+h_u)-(d'_v+h_v)=w_{v,u}\)

此时发现如果将新的势能 \(h'_u\gets d'_u+h_u\) 即满足反向边 \(=0\),再来验证一下原先就存在的边:

根据三角形不等式 \(d'_u+w_{u,v}+h_u-h_v\geq d'v\)

从而也有

\(w_{u,v}+(d'_u+h_u)-(d'_v+h_v)\geq 0\)

希望写得没问题/yun 不知道哪里常数写大了一点可能 至少比之前写的费用流要快。

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<random>
#include<assert.h>
#define pb emplace_back
#define mp make_pair
#define fi first
#define se second
#define dbg(x) cerr<<"In Line "<< __LINE__<<" the "<<#x<<" = "<<x<<'\n'
#define dpi(x,y) cerr<<"In Line "<<__LINE__<<" the "<<#x<<" = "<<x<<" ; "<<"the "<<#y<<" = "<<y<<'\n'
#define DE(fmt,...) fprintf(stderr, "Line %d : " fmt "\n",__LINE__,##__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,int>pli;
typedef pair<ll,ll>pll;
typedef pair<int,ll>pil;
typedef vector<int>vi;
typedef vector<ll>vll;
typedef vector<pii>vpii;
typedef vector<pll>vpll;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
	r=0;bool w=0;char ch=getchar();
	while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
	while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
	return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x,T2& ...y){read(x);read(y...);}
const int N=1000010;
const int inf=0x7fffffff;
const ll INF=0x7fffffffffffffff;
int n,m,S,T,tot;
int head[N],lst[N],pre[N],vis[N],ent=1;
ll flow[N],dis[N],h[N];
struct Edge{
	int fr,to,nxt;
	ll fl,co;
}e[N<<1];
inline void add(int x,int y,ll w,ll c){
	e[++ent]={x,y,head[x],w,c};head[x]=ent;
	e[++ent]={y,x,head[y],0,-c};head[y]=ent;
}
void spfa(){
	for(int i=1;i<=tot;i++)dis[i]=INF;
	queue<int>q;
	q.push(S);dis[S]=0;
	while(!q.empty()){
		int x=q.front();q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=e[i].nxt){
			int v=e[i].to;
			if(dis[v]>dis[x]+e[i].co+h[x]-h[v]&&e[i].fl){
				dis[v]=dis[x]+e[i].co+h[x]-h[v];
				if(!vis[v]){
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
}
bool dij(){
	for(int i=2;i<=tot;i++)
		if(dis[i]!=INF)
			h[i]+=dis[i];
	for(int i=1;i<=tot;i++)lst[i]=pre[i]=vis[i]=0,dis[i]=flow[i]=INF;
	priority_queue<pll,vpll,greater<pll>>q;
	q.push(mp(0,S));dis[S]=0;
	while(!q.empty()){
		int x=q.top().se;q.pop();
		if(vis[x])continue;
		vis[x]=1;
		for(int i=head[x];i;i=e[i].nxt){
			int v=e[i].to;
			if(dis[v]>dis[x]+e[i].co+h[x]-h[v]&&e[i].fl){
				dis[v]=dis[x]+e[i].co+h[x]-h[v];
				pre[v]=x;lst[v]=i;
				flow[v]=min(flow[x],e[i].fl);
				q.push(mp(dis[v],v));
			}
		}
	}
	return pre[T]>0;
}
void MCMF(){
	spfa();
	ll mxfl=0,mnco=0;
	while(dij()){
		mxfl+=flow[T];
		mnco+=(dis[T]-h[S]+h[T])*flow[T]; 
		int now=T;
		while(now!=S){
			e[lst[now]].fl-=flow[T];
			e[lst[now]^1].fl+=flow[T];
			now=pre[now];
		}
	}
	cout << mxfl << ' ' << mnco << '\n';
}
signed main(){
	read(n,m,S,T);tot=n;
	for(int i=1;i<=m;i++){
		int u,v,w,c;read(u,v,w,c);
		add(u,v,w,c);
	}
	MCMF();
    #ifdef do_while_true
		cerr<<'\n'<<"Time:"<<clock()<<" ms"<<'\n';
	#endif
	return 0;
}

标签:typedef,now,对偶,int,Primal,flow,Dual,include,dis
From: https://www.cnblogs.com/do-while-true/p/17822656.html

相关文章

  • 凸优化 | Lagrange 对偶:极大极小不等式的证明
    背景:Lagrange对偶:对于优化问题\[\begin{aligned}&\mathrm{minimize}~~&f_0(x)\\&\mathrm{subject~to}~~&f_i(x)\le0,~~h_j(x)=0\end{aligned}\]可以建立其Lagrange对偶函数\(L(x,λ,\nu)=f_0(x)+\sumλ_if_i(x)+\sum\nu_jh_j(x)\),\......
  • Graph Neural Networks with Adaptive Residual
    目录概符号说明AirGNN代码LiuX.,DingJ.,JinW.,XuH.,MaY.,LiuZ.andTangJ.Graphneuralnetworkswithadaptiveresidual.NIPS,2021.概基于UGNN框架的一个更加鲁棒的改进.符号说明\(\mathbf{A}\in\mathbb{R}^{n\timesn}\),邻接矩阵;\(\mathbf{D}......
  • 无涯教程-Clojure - Accessing Individual Fields函数
    可以通过与结构对象一起访问键来访问结构的各个字段。AccessingIndividual-语法:keystructure-name参数   - "key"是结构中的键值,"structure-name"是作为相应关键字的结构。返回值 - 将返回与键关联的值。以下程序显示了有关如何使用它的示例。AccessingI......
  • GRLSTM:基于图的残差LSTM轨迹相似性计算《GRLSTM: Trajectory Similarity Computation
    2023年10月18日,14:14。来不及了,这一篇还是看的翻译。论文:GRLSTM:TrajectorySimilarityComputationwithGraph-BasedResidualLSTM(需要工具才能访问)Github: AAAI2023的论文。 摘要轨迹相似性的计算是许多空间数据分析应用中的一项关键任务。然而,现有的方法主要是......
  • 《Deep Residual Learning for Image Recognition》阅读笔记
    论文标题《DeepResidualLearningforImageRecognition》撑起CV界半边天的论文Residual:主要思想,残差。作者何恺明,超级大佬。微软亚研院属实是人才辈出的地方。初读摘要提问题:更深层次的神经网络更难训练。提方案:提出了残差网络解决深层网络训练的问题。这也......
  • Dual Graph enhanced Embedding Neural Network for CTR Prediction
    目录概DG-ENNGuoW.,SuR.,TanR.,GuoH.,ZhangY.,LiuZ.,TangR.andHeX.Dualgraphenhancedembeddingneuralnetworkforctrprediction.KDD,2021.概图网络用在精排上,作者的出发点是为了解决(user/item)特征的稀疏性和用户交互序列的稀疏性,不过这出......
  • 2023-02-06Fix dual system time problem copy
    +++title="Fixdualsystemtimeproblem"description=""date=2023-02-06T14:21:50+08:00featured=falsecomment=truetoc=truereward=truecategories=[""]tags=["ubuntu"]series=[]images=[]+......
  • CNN -- Simple Residual Network
    Smiling&Weeping ----我爱你,从这里一直到月亮,再绕回来说明:1.要解决的问题:梯度消失2.跳连接,H(x)=F(x)+x,张量维度必须一致,加完后再激活。不要做pooling,张量的维度会发生变化 1#先是1个卷积层(conv,maxpooling,relu),然后Res......
  • 跟着GPT学习拉格朗日对偶性
      再来一个例子:  拉格朗日对偶性如何通俗理解呢?有没有实际例子可以说明下? 拉格朗日对偶性是优化理论中的一个重要概念,尤其在机器学习和运筹学中经常遇到。在对偶性中,我们从一个优化问题(称为原问题)中衍生出另一个相关的优化问题(称为对偶问题)。这两个问题之......
  • 【题解】CF1854A2 Dual (Hard Version)
    你考虑我们A1只需要通过自加凑一个最大的数,然后将所有的数都变成正数,最后做一次前缀和即可。(不懂可以看看落谷题解)好,我们现在去看HardVersion的\(31\)次操作怎么分配:前缀和(全为正)/后缀和(全为负)——\(19\)次还剩下\(12\)次,不知道该怎么做。我们的目标便变......