【学习笔记】浅谈线性规划的对偶性

线性规划

形式化地说,就是对于一个未定的列向量 x x x(长度为 n n n),以及一个已知的列向量 c c c (长度为 n n n),求
c T x c^{T}x cTx

的最值,以及,对 x x x 的限制是 A x < ( ≤ ) b Ax<(\leq) b Ax<()b

其中 A A A 是一个 m × n m\times n m×n 的已知矩阵, b b b 是一个长为 m m m 的已知列向量。

这里的小于符号(其实完全可以换成大于,不重要)表示左边列向量的每一项都分别小于右边列向量的对应项。

线性规划的对偶性

直观的图解法告诉我们:
max ⁡ { c T x ∣ A x < b } = min ⁡ { b T y ∣ A T y > c } \max\{c^{T}x|Ax<b\}=\min\{b^Ty|A^{T}y>c\} max{cTxAx<b}=min{bTyATy>c}

左边的线性规划问题和右边的线性规划问题互为对偶问题,二者的答案相等。

实际运用中经常可以遇见这样的情况:把一个线规问题转化成对偶问题后,忽然就可以贪心了。非常好用。

例题

CF671D Roads in Yusland

我们把原问题用线性规划表示出来,令

  • c c c :长度为 m m m 的向量,表示各个路径的权值
  • A A A ( n − 1 ) × m (n-1)\times m (n1)×m 的矩阵, A [ i ] [ j ] A[i][j] A[i][j] 为 1 表示第 i i i 条边在第 j j j 条路径里面。
  • b b b :长度为 n − 1 n-1 n1 ,全为 1 的列向量。

那么我们要求的就是
min ⁡ { c T x ∣ A x ≥ b } \min\{c^{T}x|Ax\geq b\} min{cTxAxb}

x x x 本来随意,但是据题意可知最优方案 x x x 一定是个 01 向量。

这本来不那么好贪心,但是我们可以转化成对偶问题看看
min ⁡ { c T x ∣ A x ≥ b } = max ⁡ { b T y ∣ A T y ≤ c } \min\{c^{T}x|Ax\geq b\}=\max\{b^Ty|A^{T}y\leq c\} min{cTxAxb}=max{bTyATyc}

右边那个问题就是,给每条边定一个非负整数权值,确保每条路径的边权和不超过路径权值,最大化全体边权和。

这个就可以贪心了,我们从叶子往上确定边权,贪心选取最大边权就行了,用一些数据结构维护路径对每条边的限制,可并堆可以实现一个 log ⁡ \log log

CODE

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#pragma GCC optimize(2)
using namespace std;
#define MAXN 300005
#define MAXM (1<<20|5)
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define PR pair<int,int>
#define UIN unsigned int
int xchar() {
	static const int maxn = 1000000;
	static char b[maxn];
	static int pos = 0,len = 0;
	if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
	if(pos == len) return -1;
	return b[pos ++];
}
// #define getchar() xchar()
inline LL read() {
	LL f = 1,x = 0;int s = getchar();
	while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
	while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
	return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
inline void putnum(LL x) {
	if(!x) {putchar('0');return ;}
	if(x<0) putchar('-'),x = -x;
	return putpos(x);
}
inline void AIput(LL x,int c) {putnum(x);putchar(c);}

int n,m,s,o,k;
int hi[MAXN];
struct it{
	int nm,lz;
	int s[2],d;
	it(){nm=s[0]=s[1]=d=lz=0;}
}tre[MAXN];
int upd(int x) {
	if(tre[tre[x].s[0]].d < tre[tre[x].s[1]].d) swap(tre[x].s[0],tre[x].s[1]);
	tre[x].d = tre[tre[x].s[1]].d + 1; return x;
}
void pushdown(int x) {
	if(tre[x].lz) {
		if(tre[x].s[0]) tre[tre[x].s[0]].nm += tre[x].lz,tre[tre[x].s[0]].lz += tre[x].lz;
		if(tre[x].s[1]) tre[tre[x].s[1]].nm += tre[x].lz,tre[tre[x].s[1]].lz += tre[x].lz;
		tre[x].lz = 0;
	} return ;
}
int merg(int a,int b) {
	if(!a || !b) return a|b;
	if(tre[a].nm > tre[b].nm) swap(a,b);
	pushdown(a); tre[a].s[1] = merg(tre[a].s[1],b);
	return upd(a);
}
void Pop(int &x) {
	pushdown(x);
	x=merg(tre[x].s[0],tre[x].s[1]);
}
int hd[MAXN],nx[MAXN<<1],v[MAXN<<1],cne;
void ins(int x,int y) {
	nx[++ cne] = hd[x]; v[cne] = y; hd[x] = cne;
}
LL ans = 0;
bool flag = 1;
int d[MAXN],rt[MAXN],ct[MAXN];
void dfs(int x,int ff) {
	d[x] = d[ff] + 1;
	for(int i = hd[x];i;i = nx[i]) {
		if(v[i] != ff) {
			dfs(v[i],x);
			ct[x] += ct[v[i]];
			if(ct[v[i]] <= 0) flag = 0;
			while(rt[v[i]] && d[hi[rt[v[i]]]] > d[x]) Pop(rt[v[i]]);
			if(rt[v[i]]) {
				ans += tre[rt[v[i]]].nm;
				tre[rt[v[i]]].lz -= tre[rt[v[i]]].nm;
				tre[rt[v[i]]].nm = 0;
			}
			rt[x] = merg(rt[x],rt[v[i]]);
		}
	} return ;
}
int main() {
	n = read(); m = read();
	for(int i = 1;i < n;i ++) {
		s = read(); o = read();
		ins(s,o); ins(o,s);
	}
	for(int i = 1;i <= m;i ++) {
		s = read(); hi[i] = read();
		ct[s] ++; ct[hi[i]] --;
		k = read();
		tre[i] = it();
		tre[i].nm = k;
		rt[s] = merg(rt[s],i);
	}
	dfs(1,0);
	if(!flag) ans = -1;
	AIput(ans,'\n');
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《机器学习学习笔记.pdf》是一本关于机器学习学习笔记的电子书,其内容涵盖了机器学习的基本概念、算法原理和实践应用等方面。 该电子书的主要内容包括但不限于以下几个方面: 1. 机器学习基础:介绍了机器学习的基本概念、发展历史和核心原理,帮助读者建立起对机器学习的整体认识和理解。 2. 机器学习算法:详细介绍了常见的机器学习算法,包括监督学习算法(如线性回归、逻辑回归、决策树、支持向量机等)、无监督学习算法(如聚类算法、降维算法等)和强化学习算法等,使读者能够了解和掌握不同类型的机器学习算法及其应用场景。 3. 机器学习实践:讲解了机器学习的实践方法和流程,涵盖了数据预处理、特征工程、模型选择和评估等方面的内容,帮助读者掌握如何在实际问题中应用机器学习技术。 4. 应用案例:通过实际案例的介绍和分析,展示了机器学习在自然语言处理、计算机视觉、推荐系统等领域的应用,激发读者对机器学习在实际问题中的应用的兴趣和思考能力。 通过阅读《机器学习学习笔记.pdf》,读者可以系统地学习机器学习的基础知识和算法原理,了解机器学习的应用场景和实践方法,并通过实际案例的分析加深对机器学习技术的理解。这本电子书可以作为机器学习初学者的入门学习资料,也适合有一定机器学习基础的读者作为参考和进一步学习的资料。希望通过这本电子书的阅读,读者能够理解和掌握机器学习的相关知识,为未来在机器学习领域的学习和研究打下坚实的基础。 ### 回答2: 《机器学习学习笔记.pdf》是一本介绍机器学习学习资料。机器学习是一种通过利用数据来训练计算机算法的方法,使其能够自动地从数据中学习和提高性能。这本学习笔记涵盖了机器学习的基本概念、原理和方法,适合初学者和对机器学习感兴趣的读者。 首先,学习笔记从机器学习的基本概念入手,包括机器学习的定义、应用领域以及机器学习的三个主要任务:监督学习、无监督学习和强化学习。然后,详细介绍了机器学习的基本原理,如训练集、测试集、特征选择和模型评估等。此外,学习笔记还介绍了几种常见的机器学习算法,如决策树、支持向量机和深度学习等。 除了理论知识,学习笔记还提供了实践案例和代码示例,帮助读者更好地理解和应用机器学习算法。读者可以通过实践案例来掌握机器学习算法的具体应用,并且可以利用代码示例进行实际编程实践。同时,学习笔记还讨论了机器学习的一些挑战和未来的发展方向,如数据质量、模型解释性和自动化机器学习等。 总的来说,《机器学习学习笔记.pdf》是一本全面介绍机器学习学习资料。它结合理论和实践,旨在帮助读者建立对机器学习的基本理解,并具备在实际问题中应用机器学习算法的能力。无论是初学者还是有一定机器学习基础的读者,都可以从中获得有益的知识和经验。 ### 回答3: 《机器学习学习笔记.pdf》是一本关于机器学习学习笔记文档。机器学习是人工智能领域的重要分支,它研究如何使计算机系统自动从数据中学习和改进,以完成特定任务。这本学习笔记以简洁明了的方式介绍了机器学习的基本概念、算法和实践应用。 笔记中首先介绍了机器学习的基础知识,包括监督学习、无监督学习和强化学习等不同的学习类型。然后详细讲解了常用的机器学习算法,如线性回归、逻辑回归、决策树、支持向量机等。每种算法都给出了清晰的定义和示例,并详细解释了算法的原理和应用场景。 此外,《机器学习学习笔记.pdf》还包括了机器学习的实践应用和案例分析。它介绍了如何通过Python等编程语言和机器学习库进行实际的机器学习项目开发,包括数据预处理、特征工程、模型训练和评估等环节。对于初学者来说,这部分内容非常有价值,可以帮助他们快速进入实际应用的阶段。 总结来说,《机器学习学习笔记.pdf》是一本很好的机器学习入门教材,它详细介绍了机器学习的基本概念和常用算法,并提供了实际项目的实践指导。无论是对于想要了解机器学习基础知识的初学者,还是对于已经有一定机器学习经验的开发者来说,这本学习笔记都是一本值得阅读和参考的资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值