首页 > 其他分享 >个人对于二分图匹配的学习记录

个人对于二分图匹配的学习记录

时间:2023-04-23 19:33:05浏览次数:47  
标签:二分 pre const 记录 int ll long 匹配

二分图

匈牙利算法

下面展示的是dfs实现的写法。

//洛谷P3386 二分图最大匹配 匈牙利算法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1505;
const int M = 50005;

int head[N], eid;

struct Edge {
	int v, w, next;
} e[M << 1];

void addEdge(int u, int v, int w) {
	e[eid] = {v, w, head[u]};
	head[u] = eid++;
}

int match[N], vis[N];// match 内下标为右部点,表示与右部点匹配的是第几个左部点
					 // vis 用于标记当前增广操作有没有遇到过该点,所以每次增广时都要清空。
bool dfs(int u) {
//	cout << endl;
//	cout << u << ": ";
	for (int i = head[u]; ~i; i = e[i].next) {
		int v = e[i].v;
		if (!vis[v]) {
			vis[v] = 1;//注意标记
	//		cout << v <<" ";
			if (!match[v] || dfs(match[v])) { // 右部点无匹配或右部点原配存在其他匹配
				match[v] = u; //该右部点匹配为当前点
		//		cout << "end " << u << endl;
				return true;
			}
		}
	}
//	cout << "end " << u << endl;
	return false;
}
//以上注释输出代码可用于打印增广路。

int main() {

	ios::sync_with_stdio(false);
	cin.tie();

	memset(head, -1, sizeof head);

	int n, m, e;
	cin >> n >> m >> e;

	for (int i = 1; i <= e; i++) {
		int u, v;
		cin >> u >> v;
		addEdge(u, v, 1);
	}
	
	int ans = 0;
	
	for (int i = 1; i <= n; i++) {
		memset(vis, 0, sizeof vis);
		if (dfs(i)) {
			ans++;
		}
	}

	cout << ans << endl;
	return 0;
}
//匈牙利算法的本质是优先考虑当前左部点的匹配,如果对应右部点无匹配则改为当前匹配,
//如果有匹配,则查询该右部点的原配能否与其他右部点匹配,可以则增广路增加,否则查询下一右部点。
//每次一个点成功匹配,则二分图最大匹配边数增加(显然)
//匈牙利算法的时间复杂度为 O(VE),其中 V 为左部点个数, E 为边的个数
//查找二分图的最大匹配,也可以用增广路算法(Augmenting Path Algorithm),时间复杂度为O(NE)

下面展示的是bfs实现的写法

//UOJ#78 二分图最大匹配模板题
#include<bits/stdc++.h> 
#include<queue>

using namespace std;
typedef long long ll;

const int N = 505;
const int M = 250005;

struct Edge{
	int v, w, next;
}e[M];

int head[N],eid;

void addEdge(int u, int v, int w) {
	e[eid] = {v, w, head[u]};
	head[u] = eid++;
} 

int nl, nr, m;

int matchx[N],matchy[N], visx[N], visy[N], pre[N];//pre用于记录路径
queue<int> q;

void aug(int v) {
	while (v) {
		int t = matchx[pre[v]]; //  t 为 v 当前所想匹配的左部点的原配 
		matchx[pre[v]] = v; // 当前左部点匹配当前右部点 
		matchy[v] = pre[v];//匹配 
		v = t;//更改原配的匹配 
	}
}

bool bfs(int s) {
	memset(visy, 0, sizeof visy);
	memset(visx, 0, sizeof visx);
	memset(pre, 0 ,sizeof pre);
	
	while(!q.empty()) q.pop();
	q.push(s);
	
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		
		visx[u] = 1;
		
		for (int i = head[u]; ~i; i = e[i].next) {
			int v = e[i].v;
			
			if (!visy[v]) {
				
				visy[v] = 1;
				pre[v] = u;
				
				if(!matchy[v]) {
					aug(v); // 修改匹配
					return 1;
				} else {
					q.push(matchy[v]);
				}
				
			}
			
		}
		
	}
	
	return false;
}


int main() {
	
	memset(head, -1, sizeof head);
	
	cin >> nl >> nr >> m;
	
	for (int i = 1; i <= m; i++) {
		int u, v;
		cin >> u >> v;
		addEdge(u, v, 1);
	}
	
	int ans = 0;
	
	for (int i = 1; i <= nl; i++) {
		if (bfs(i)) {
			ans++;
		}
	}
	
	cout << ans << endl;
	
	for (int i =1; i<= nl; i++) {
		cout << matchx[i] << " ";
	}
	cout << endl;
	
	return 0;
}

匈牙利算法相关例题 : 洛谷P2759 模板题 , 洛谷P1129 矩阵游戏


//洛谷 P1129 矩阵游戏
//题目要求我们将 1 移动到 (1,1) (2,2)这种位置上
//对于每一行,由于我们可以进行列交换操作,所以只需要在当前行上找一个存在的列即可
//对于每一列,由于我们可以进行行交换操作,所以只需要在当前列上找一个存在的行即可
//而由于同一个位置上的 1 不能被行交换和列交换到两个位置,这样 1 的个数就增加了
//所以此时,每一行每一列就构成了一一对应的关系,即匹配
//至此,题目便转化成了二分图匹配问题,只需要最终行与列的匹配数等于 n 即可。
//证明:由于行与列都有 n 个,所以只有n 个行都找到对应的列,也就是 n 个匹配时,才能得到 n 个(i,i) 的位置

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 505;
const int M =40005;

int head[N],eid;

struct Edge {
	int v, w, next;
} e[M<<1];

void addEdge(int u, int v, int w) {
	e[eid] = {v, w, head[u]};
	head[u] = eid++;
}

int match[N], vis[N];

bool dfs(int u) {
	for (int i = head[u]; ~i; i = e[i].next) {
		int v = e[i].v;
		
		if (!vis[v]) {
			vis[v] = 1;
			if (!match[v] || dfs(match[v])) {
				match[v] = u;
				return true;
			}
		}
		
	}
	return false;
}


int main () {

	ios::sync_with_stdio(false);
	cin.tie();

	int T;
	cin >> T;
	while(T--) {
		memset(head, -1, sizeof head);
		eid = 0;
		
		int n;
		cin >> n;
		
		for (int i = 1; i <= n; i++) {
			match[i] = 0;
			for (int j = 1; j <= n; j++) {
				int x;
				cin >> x;
				if (x == 1) {
					addEdge(i, j, 1);
				}
			}
		}
		
		int ans = 0;
		
		for (int i = 1; i <= n; i++) {
			memset(vis, 0, sizeof vis);
			
			if (dfs(i)) {
				ans++;
			}
			
		}
		
		if (ans == n) {
			puts("Yes");
		}else puts("No");
		
	}

	return 0;
}

KM算法

KM算法主要用于带权值的二分图匹配问题,通常用来找总权值最大或最小的完美匹配。

例题洛谷P1559 运动员最佳匹配问题

//DFS实现版本,时间复杂度比较大,后续更新BFS实现版本

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105;
const int M =4005;
const ll INF = 0X7F7F7F7F;

struct Edge{
	int v, w, next;
}e[M<<1];

int head[N], eid;

void addEdge(int u, int v, int w) {
	e[eid] = {v, w, head[u]};
	head[u] = eid++;
}

ll a[N][N];
int match[N];
bool visa[N], visb[N];
ll la[N], lb[N];
int n;
ll delta = INF;

bool dfs(int x) {
	visa[x] = 1;
	for (int i = head[x]; ~i; i = e[i].next) {
		int v = e[i].v;
		
		if (!visb[v]) {
			
			if (la[x] + lb[v] - a[x][v] == 0) {
				visb[v] = 1;
				
				if (!match[v] || dfs(match[v])) {
					match[v] = x;
					return true;
				}
				
			}else delta = min (delta, la[x] + lb[v] - a[x][v]);
				
		}
		
	}
	return false;
}


ll km() {
	
	for (int i = 1; i <= n; i++) {
		la[i] = -INF;
		lb[i] = 0;
		
		for (int j = head[i]; ~j; j = e[j].next) {
			int v = e[j].v;
			la[i] = max(la[i], a[i][v]);
		}
		
	}
	
	for (int i = 1; i <= n; i++) {
		while (1) {
			memset(visa, 0, sizeof visa);
			memset(visb, 0 ,sizeof visb);
			delta = INF;
			
			if (dfs(i)) break;
			
			for (int j = 1; j <= n; j++) {
				if (visa[j]) la[j] -= delta;
				if (visb[j]) lb[j] += delta; 
			}
			
		}
	}// 我们最多会在每一个右部点上都有一次找不到匹配的结果,这样最多会有n次修改delta的操作。
    //也就是说,km + dfs的时间复杂度会被卡到n的四次方。
	
	ll ans = 0;
	for (int i = 1; i <= n; i++) {
		ans += a[match[i]][i];
	}
	return ans;
	
}

int main () {
	
	memset(head, -1,sizeof head);
	
	cin >> n;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> a[i][j];
		}
	}
	
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			ll x;
			cin >> x;
			a[j][i] *= x;
			addEdge(j, i, a[j][i]);
		}
	}
	
	cout << km() << endl;
	
	
	return 0;
}

从上述代码可以发现 : 每次用dfs增广,时间复杂度为 \(n ^ 2\),而每次扩大相等子图只能加入一条边,最多会有 \(n^2\) 条边,也就是说,km + dfs 的时间复杂度会被卡到 \(n ^ 4\) 。

解决这个问题的方法也很简单,我们只要换用bfs来实现,在每次扩大完子图后,在 bfs 外将所有可增广点入队,这样我们就将 n 次 增广操作与 bfs 分开了,时间复杂度也被降到了 \(n^3\) 。

//km + bfs 实现
//例题 UOJ#80
#include<bits/stdc++.h>
#include<queue>
using namespace std;
typedef long long ll;
const int N =505;
const int M = 160006;
const ll INF = 1e18+7;

int nl, nr ,m;
int matchx[N],matchy[N];
ll lx[N],ly[N];
ll a[N][N], slack[N], d;
int pre[N];
bool visx[N], visy[N];
queue<int> q;

void aug(int v) {
	while (v) {
		int t = matchx[pre[v]];
		matchx[pre[v]] = v;
		matchy[v] = pre[v];
		v = t;
	}
}

void bfs(int s) {
	for (int i =1; i <= nr; i++) {
		slack[i] = INF;
	}
	memset(visx, 0 ,sizeof visx);
	memset(visy, 0, sizeof visy);
	memset(pre, 0, sizeof pre);

	while(!q.empty()) q.pop();
	q.push(s);

	while (1) {
		while (!q.empty()) {
			int	u = q.front();
			q.pop();
			visx[u] = 1;

			for (int v = 1; v <= nr; v++) {
				if (!visy[v]) {

					if (lx[u] + ly[v] - a[u][v] < slack[v]) {
						slack[v] = lx[u] + ly[v] - a[u][v];
						pre[v] = u;

						if (!slack[v]) { // 顶标之和大于边权时可加入
							visy[v] = 1;
							if (!matchy[v]) {
								aug(v);
								return;
							} else q.push(matchy[v]);
						}

					}

				}
			}

		}

		d = INF;
		for (int i = 1; i<= nr; i++) {
			if (!visy[i]) d = min(d, slack[i]);
		}
		if (d == INF) break;

		for (int i = 1; i<= nl; i++) if (visx[i]) lx[i] -= d;
		for (int i = 1; i<= nr; i++) if (visy[i]) ly[i] += d;
			else slack[i] -= d;
		// slack[v] -= d ,因为当右部点v没有在路径上时顶标不变,而与之相连的左部点顶标减少
		//所以 lx + ly 的值减小了 d
		
        
        //将可增广点加入队列中
		for (int i = 1; i <= nr; i++) {
			if (!visy[i] && !slack[i]) {
				visy[i] = 1;
				if (!matchy[i]) {
					aug(i);
					return;
				} else q.push(matchy[i]);
			}
		}

	}


}

void km() {
	for (int u = 1; u <= nl; u++) {
		for (int v = 1; v <= nr; v++) {
			lx[u] = max(lx[u], a[u][v]);
		}
	}

	for (int i = 1; i <= nl; i++) {
		bfs(i);
	}

}


int main() {

	cin >> nl >> nr >> m;
	if (nr < nl) nr = nl; //右部点一定大于等于左部点,不满足则创建虚点。
	
//	for (int i = 1; i <= nl; i++) {
//		for (int j = 1; j <= nr; j++) {
//			a[i][j] = -INF;
//		}
//	}
    //如果优先满足最大匹配再满足权值最大,则给边赋值负无穷
    //如果优先满足权值最大,则给边赋值为0
	
	for (int i = 1; i <= m; i++) {
		int u, v;
		cin >> u >> v;
		cin >> a[u][v];
	}

	ll ans = 0;

	km(); 

	for (int i = 1; i <= nl; i++) ans += lx[i];
	for (int i = 1; i <= nr; i++) ans += ly[i];
	//总权值和为顶标之和
	cout << ans << endl;

	for (int i = 1; i <= nl; i++) {
		if (a[i][matchx[i]]) cout << matchx[i] << " "; //边权<=0时,该边为虚边
		else cout << 0 << " ";
	}

	cout << endl;

	return 0;
}
//洛谷P6577 模板题 二分图最大权完美匹配
//与上一题不同,本题要求优先满足完美匹配,再满足权值最大。
#include<bits/stdc++.h>
#include<queue>

using namespace std;
typedef long long ll;

const ll INF = 1e12;
const int N = 1005;
int n, m;
int nl, nr;

ll a[N][N];

int matchx[N], matchy[N], pre[N];
ll lx[N], ly[N];
ll slack[N], d;
bool visx[N], visy[N];
queue<int> q;

void aug(int v) {
	while(v) {
		int t = matchx[pre[v]];
		matchx[pre[v]] = v;
		matchy[v] = pre[v];
		v = t;
	}
}


void bfs(int s) {

	for (int i = 1; i <= nr; i++) {
		slack[i] = INF;
	}

	memset(visx, 0, sizeof visx);
	memset(visy, 0, sizeof visy);
	memset(pre, 0, sizeof pre);

	while(!q.empty()) q.pop();
	q.push(s);

	while(1) {
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			visx[u] = 1;

			for (int v = 1; v <= nr; v++) {
				if (!visy[v]) {

					if (lx[u] + ly[v] - a[u][v] < slack[v]) {
						slack[v] = lx[u] + ly[v] - a[u][v];
						pre[v] = u;
					}

					if (!slack[v]) {
						visy[v] = 1;
						if (!matchy[v]) {
							aug(v);
							return;
						} else q.push(matchy[v]);
					}

				}
			}

		}

		d = INF;

		for (int i = 1; i <= nr; i++) {
			if (!visy[i]) d = min(d, slack[i]);
		}

		if (d == INF) break;

		for (int i = 1; i <= nl; i++) if (visx[i]) lx[i] -= d;
		for (int i = 1; i <= nr; i++) if (visy[i]) ly[i] += d;
			else slack[i] -= d;

		for (int i = 1; i <= nr; i++) {
			if (!visy[i] && !slack[i]) {
				visy[i] = 1;
				if (!matchy[i]) {
					aug(i);
					return;
				} else q.push(matchy[i]);
			}
		}

	}

}

void km() {
	
	for (int u = 1; u <= nl; u++) {
		for (int v = 1; v <= nr; v++) {
			lx[u] = max(lx[u], a[u][v]);
		}
	}

	for (int i = 1; i <= nl; i++) {
		bfs(i);
	}

}

int main () {
	
	freopen("P6577_11.in","r",stdin);
	
	cin >> n >> m;

	nl = nr = n;

	for (int i = 1; i <= n<<1; i++) {
		lx[i] = -INF;
		for (int j = 1; j <= n<<1; j++) {
			a[i][j] = -INF;
		}
	}

	for (int i = 1; i <= m; i++) {
		int x, y;
		cin >> x >> y;
		cin >> a[x][y];
	}

	km();

	ll ans = 0;

	for (int i = 1; i <= nl; i++) {
		ans += lx[i];
//		cout << "L: " << i << " " << lx[i] << endl;
	}

	for (int i = 1; i <= nr; i++) {
		ans += ly[i];
//		cout << "R: " << i << " " << ly[i] << endl;
	}

	cout << ans << endl;

	for (int i = 1; i <= nr; i++) {
		if (a[matchy[i]][i] != -INF) cout << matchy[i] << " ";
	}

	cout << endl;

	return 0;
}

下面是一道安徽大学校赛题的二分图最小权匹配。

显然,对于寻找最小权,我们只要将所有边权取负,再找对大权,此时的最大权的绝对值就是原图的二分图最小权。

此外,根据本题题意,所有棋子都要落到边上,可转化为二分图匹配问题,所有棋子对应左部点,而所有边上的格子对应为右部点,最终棋盘整理好即为所有棋子都要有对应的格子,即一个完美匹配,所以本题是一道二分图最小权值完美匹配问题

不过本题转化为二分图匹配问题有一个前提:在考虑棋子移动时,我们无需考虑格子上已有的棋子,也就是说我们的棋子在移动时可穿过其他棋子,因为其他棋子也可发生移动。也就是说,我们甚至无需考虑棋子的移动,只需要考虑棋子与有效格子的匹配,这样原问题就变成了一个二分图匹配问题。

当格子数量小于棋子数量时,可特判为无解,这样场上的棋子与格子数最多不会超过\(800\),对于用 bfs 实现的 km 算法,时间复杂度为 \(O(m^3)\) ,其中M为格子数。

本题的另一特点是要处理好边权,而边权也很明显,即为每个棋子到格子的曼哈顿距离。

//牛客,整理棋盘,二分图

#include<bits/stdc++.h>
#include<queue>
using namespace std;
typedef long long ll;

const int N = 405;
const int M = 805;
const int INF = 0x3f3f3f3f;
int n , m;

char c[N][N];
int a[M][M];
int posx[M], posy[M], pre[M];
int lx[M], ly[M], matchx[M], matchy[M];
int slack[M], d;
bool visx[M], visy[M];
queue<int> q;
int nl, nr;

void aug(int v) {
	while(v) {
		int t = matchx[pre[v]];
		matchx[pre[v]] = v;
		matchy[v] = pre[v];
		v = t;
	}
}

void bfs(int s) {

	for (int i = 1; i <= nr; i++) slack[i] = INF;

	memset(visx, 0, sizeof visx);
	memset(visy, 0, sizeof visy);
	memset(pre, 0, sizeof pre);

	while(!q.empty()) q.pop();
	q.push(s);

	while(1) {
		while(!q.empty()) {
			int u = q.front();
			q.pop();
			visx[u] = 1;
			for (int v = 1; v <= nr; v++) {
				if (!visy[v]) {
					
					if (lx[u] + ly[v] - a[u][v] < slack[v]) {
						slack[v] = lx[u] + ly[v] - a[u][v];
						pre[v] = u;
					}
					
					if (!slack[v]) {
						visy[v] = 1;
						if (!matchy[v]) {
							aug(v);
							return;
						}else q.push(matchy[v]);
					}
					
				}
				
				
			}
		}
		
		d = INF;
		
		for (int i = 1; i <= nr; i++) {
			if (!visy[i]) d = min(d, slack[i]);
		}
		
		if (d == INF) break;
		
		for (int i = 1; i <= nl; i++) if (visx[i]) lx[i] -= d;
		for (int i = 1; i <= nr; i++) if (visy[i]) ly[i] += d;
		else slack[i] -= d;
		
		for (int i = 1 ; i <= nr; i++) {
			if (!visy[i] && !slack[i]) {
				visy[i] = 1;
				if (!matchy[i]) {
					aug(i);
					return;
				}else q.push(matchy[i]);
			}
		}
		
	}

}


void km() {

	for (int i = 1; i <= nl; i++) {
		for (int j = 1; j <= nr; j++) {
			lx[i] = max(lx[i], a[i][j]);
		}
	}

	for (int i = 1; i <= nl; i++) {
		bfs(i);
	}

}

void init() {
	for (int i = 0 ; i <= 800; i++) {
		posx[i] = -1;
		posy[i] = -1;
		matchy[i] = matchx[i] = 0;
		lx[i] = 0;
		ly[i] = 0;
	}
}

int main() {
	int T;
	cin >> T;
	while (T--) {
		init();
		cin >> n >> m;

		int sp = n * 4 - 4;
		nl = m;
		nr = sp;
		int cnt = 1;

		for (int i = 1 ; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				cin >> c[i][j];
				if (c[i][j] == '#') {
					posx[cnt++] = (i-1) * n + j; // 记录棋子位置
				}

				a[i][j] = -INF;
			}
		}

		if (m > sp) {
			puts("-1");
			continue;
		}
		int cnty = 0;
		for (int i = 1; i <= n; i++) {
			posy[++cnty] = i;
		}

		for (int i = 2; i <= n-1; i++) {
			posy[++cnty] = (i - 1) * n + 1;
			posy[++cnty] = (i - 1) * n + n;
		}

		for (int i = 1; i <= n; i++) {
			posy[++cnty] = (n - 1) * n + i;
		}// 记录有效格子位置

		for (int i = 1; i <= m; i++) {
			for (int j = 1; j <= cnty; j++) {
				int x1 = (posx[i] - 1) / n + 1, x2 = (posy[j] - 1) / n + 1;
				int y1 = (posx[i] - 1) % n + 1, y2 = (posy[j] - 1) % n + 1;
				int w = abs(x1 - x2) + abs(y1 - y2);//处理边权
		//		cout << x1 << " " << y1 << "  ,  " << x2 << " " << y2 << ": " << w << endl; 
				a[i][j] = -1 * w;//边权取负
			}
		}

		km();
		
		int ans = 0;
		
		for (int i = 1; i <= nl; i++) ans += lx[i];
		for (int i = 1; i <= nr; i++) ans += ly[i];
		
		cout << abs(ans) << endl;

	}
	return 0;
}

标签:二分,pre,const,记录,int,ll,long,匹配
From: https://www.cnblogs.com/you-mu-jv-ruo/p/17347500.html

相关文章

  • 记录一次最近遇到的新网络诈骗经历,大家要提高警惕啊
    第一次接到诈骗电话,说是要求修改支付宝信息的,一开始说的确实是很迷惑人,一下子可能没法马上分辨出来,但是到后面说要加QQ操作什么什么的,那肯定就是有严重问题的,因为很多诈骗都是通过QQ来操作的,一听到这个就要警惕了。 他的诈骗流程是这样的:先是说你的支付宝花呗要调整利率,如果不......
  • 有重复值的二分查找
    最近在验证SQLjoin的算法,感觉在内存中实现的话,比较高效的方法就是二分查找了。但与普通二分查找不同,SQLjoin的时候左右两边的值可能会有重复,这些重复值都是要找到的。所以我对二分查找进行了升级优化,不再返还一个索引,而是返回一个索引范围,找不到就返回null实现了两个版本:1.......
  • Buildroot使用记录
     关键词:rootfs、BR2_EXTERNAL等等。 记录buildroot使用各种方法,以及解决的问题。1定制文件系统方法1.1根文件系统覆盖(BR2_ROOTFS_OVERLAY)将BR2_ROOTFS_OVERLAY指向的目录覆盖到output/target根文件系统。还可以通过都好间隔,指定多个目录。配置方式:Systemconfigurati......
  • 修改Git全部Commit提交记录的用户名Name和邮箱Email
    当我们换邮箱了,想把已经提交过的commit的邮箱和用户名改成新的时候。先把本地配置成新的gitconfiguser.name'丁少华'gitconfiguser.email'新邮箱@xx.com'这时候就可以用下面的脚本代码了在项目根目录下创建email.sh写入下面这段代码#!/bin/shgitfilter-branch......
  • C# 多线程记录
    ​ 开发中经常遇到不同的业务访问同一个数据源,而每一个业务的执行流就是一个线程,此时线程一多就会产生多线程最容易遇到的问题——并发。什么是并发?        举个很经典的例子:程序中我们经常要操作一些对象,尤其是内存中的数据             例如当......
  • RK3588 Qt 交叉编译之四:配置及编译报错记录
    运行时出现错误提示:QIconvCodec::convertToUnicode:usingLatin-1forconversion,iconv_openfailedQIconvCodec::convertFromUnicode:usingLatin-1forconversion,iconv_openfailed原因是缺少iconv库,解决方案如下:./configure后添加编译-no-iconv运行时出现错误提......
  • 关于hana数据库集群在pacemaker下的启动后变化及pcs状态记录
    对于hana数据库,两个节点、使用了pacemkaer软件进行了高可用的集群首页、我们在开机后,使用 pcsclusterstart--all,将pacemaker服务启动起来,然后就是到了关机的维护模式 然后我们使用 pcsnodeunmaintenance--all取消维护模式,才能启动资源,可以观察到hana的pacemaker的状......
  • Python正则怎么匹配\啊?
    玉容寂寞泪阑干,梨花一枝春带雨。大家好,我是皮皮。一、前言前几天在Python白银交流群【膨胀西瓜汁】问了一个Python正则表达式的问题,这里拿出来给大家分享下。下面是匹配的结果:二、实现过程这里【论草莓如何成为冻干莓】给了一个思路,在前面加个r,防止转义。后来发现\5不是反斜杠。......
  • 三大类算法:递归、排序、二分查找
    一、递归”递“+”归“。这两个意思,正是递归思想的精华所在,去的过程叫做递,回来的过程叫做归,在编程语言中对递归可以简单理解为:方法自己调用自己,只不过每次调用时参数不同而已。满足递归的条件:1、递归表达是(规律)如果一个问题的解能够拆分成多个子问题的解,拆分之后,子问题和该问题在求......
  • agc021 vp记录
    abcd都是签到题[AGC021E]BallEatChameleons有\(n\)只变色龙,一开始都是蓝色。现在你喂了\(k\)次球,每次指定一只变色龙吃下你指定颜色的球。一只变色龙从蓝色变成红色当且仅当它吃的红球比蓝球多;一只变色龙从红色变成蓝色当且仅当它吃的蓝球比红球多。求最后能使所有......