二分图(概念、相关算法和题目应用)(全面整理)
TP
- 二分图的概念:
- 二分图常用算法:
- 染色法(判断一个图是否为二分图):
- 匈牙利算法(求出二分图的最大匹配数):
- 相应题目应用:
- 二分图 染色 应用:
- Acwing:关押罪犯
- 二分图最大匹配应用:
- Acwing:棋盘覆盖
- 洛谷:矩阵游戏
- 二分图最大匹配的一些推论:
- 二分图最小点覆盖应用:
- Acwing:机械任务
- Acwing:泥地
- 二分图最大独立集应用:
- Acwing:骑士放置
- 二分图 最大路径点覆盖 与 最大路径重复点覆盖 应用:
- Acwing:捉迷藏
二分图的概念:
二分图通常针对 无向图 问题(有些题目虽然是有向图,但一样有二分图性质)
在一张图中,如果能够把全部的点分到 两个集合 中,保证两个集合内部没有 任何边 ,图中的边 只存在于两个集合之间,这张图就是二分图
——————————————————————————————————————————
二分图常用算法:
染色法(判断一个图是否为二分图):
算法原理就是,用 黑 与 白 这两种颜色对图中点染色(相当于给点归属一个集合),一个点显然不能同时具有两种颜色,若有,此图就不是二分图
代码:
bool dfs(int u, int c) {color[u] = c;//当前点先染色for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];//对于这个点连接的所有的点if (color[j]) {//如果已经被染过色了if (color[j] == c)return false;//就需要判断一下,如果两点颜色一样,染色就冲突了}else if (!dfs(j, 3 - c))return false;//否则dfs去染下一个结点,赋予的颜色肯定要跟 c 不一样//3 - 1 == 2,3 - 2 == 1//同时传回染色成功与否的信息}return true;
}bool check() {memset(color, 0, sizeof color);//0 —— 未染色,1 —— 黑色,2 —— 白色for (int i = 1; i <= n; i++)if (color[i] == 0)//一旦某个点没染过色,dfs去染色if (!dfs(i, 1))return false;//如果传回false显然失败,此图不是二分图return true;//否则true
}
遍历了这张图的点和边,时间复杂度O(n+m)O(n + m)O(n+m)
——————————————————————————————————————————
匈牙利算法(求出二分图的最大匹配数):
满足 是二分图 这个前提,才能使用匈牙利算法
所谓 最大匹配数 的意思就是:
两个集合分别选一个点,这两个点之间有边就确认一段关系(一个集合中的两点 占有 另一集合中同一个点 是不合法的 一夫一妻(确信) ),最多的关系数量就是这张二分图的最大匹配
代码:
bool find(int x) { //标准匈牙利for (int j = 1; j <= n; j++)if (!st[j] && g[x][j]) { //x 点连向的所有点(因为是二分图,所以这些点都在右集合),如果存在边且没标记过st[j] = true;//标记一下,防止多次遍历int t = match[j];//右集合中该点的匹配对象if (!t || find(t)) { //没对象就可以和 x 匹配,有的话就让 t 尝试更改对象,能更改就和 x 匹配,不能就falsematch[j] = x;return true;}}return false;
}int main() {cin >> n;int ans = 0;for (int i = 1; i <= n; i++) { //遍历左集合memset(st, 0, sizeof st);//每次都要重置标记if (find(i))ans++;//一旦有一个匹配,数量就++}cout << ans;return 0;
}
最坏情况会每个点遍历全部边一次,所以时间复杂度是O(nm)O(nm)O(nm)
但匈牙利算法还是很优秀的,大部分情况时间都比较小
如果想要更优秀的算法左转 网络流 吧,匈牙利匹配本质上还是网络流的一种特殊形式,网络流可以更好地解决此类问题。网络流真是太简单了bushi
——————————————————————————————————————————
相应题目应用:
二分图 染色 应用:
Acwing:关押罪犯
这道题就变成了 如何让二分图 两集合之间的边权 尽可能大(使得集合内部边权尽可能小,冲突也就没那么激烈)
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 20010, M = 200010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int h[N], e[M], ne[M], w[M], idx;
int color[N];//染色,记录该点的状态:0 —— 未染色、1 —— 染白、2 —— 染黑void add(int a, int b, int x) {e[idx] = b, w[idx] = x, ne[idx] = h[a], h[a] = idx++;
}bool dfs(int u, int c, int mid) {color[u] = c;//染该点for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];if (w[i] <= mid)continue;//mid是答案,是设定的集合内部最大边权,如果该边小于等mid,边两点显然可以随意处理,放在一个集合内也行//否则,该边两点就严格要放在两个不同集合,防止冲突if (color[j]) { //连向的点若被染过色if (color[j] == c)return false;//显然色不能相同}else if (!dfs(j, 3 - c, mid))return false;//没被染过就染该点}return true;//成功
}bool check(int mid) {mem(color, 0);//每次重新对点染色for (int i = 1; i <= n; i++)if (color[i] == 0)//枚举每一个点是因为有可能有多个连通块if (!dfs(i, 1, mid))return false;//要保证都为二分图return true;
}int main() {cinios;cin >> n >> m;mem(h, -1);for (int i = 0; i < m; i++) {int a, b, x;cin >> a >> b >> x;add(a, b, x);//二分图通常针对的都是无向图add(b, a, x);}int l = 0, r = 1e9;//二分答案while (l < r){int mid = l + r >> 1;//mid 即是最小的最大影响力//比 mid 小的影响显然都可以随意塞到监狱中//比 mid 大的影响要让其尽可能不存在(即一边两点分别在图的两个不同子集中)//也就是询问能否用比 mid 大的边建立一个二分图if (check(mid))r = mid;//能的话显然包含答案else l = mid + 1;//不能就要增大,右移往答案靠拢}cout << l;return 0;
}
——————————————————————————————————————————
二分图最大匹配应用:
Acwing:棋盘覆盖
看上去像状压dp,但一看数据范围21002^{100}2100状压肯定炸,所以探讨一下是否具有二分图的性质
如果把每个格子看成点,放置骨牌(长2宽1)的操作可以看成 两点之间连一条边
那每个格子能放置骨牌就有四种情况四个方向连四条边(除非另一个格子被禁止放置)
可以发现的是,能放置最多骨牌 == 能不重复尽可能多地选取边 == 最大匹配数量
之前说过,求最大匹配的前提是这张图是二分图,所以我们需要判断下这张图是否具有二分图的性质
纸上作画一下便可发现,奇数格/偶数格 彼此之间是没有边的(相当于二分图中的两个集合)
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 110, M = 50010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
bool g[N][N], st[N][N];
PII match[N][N];
int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 };//防止长2宽1的骨牌,可以看作是在相邻两格之间建边(要求合法)
//结果要求最多能放多少块骨牌,就相当于 “ 最多有多少条匹配边 ”
//经过观察象棋棋盘上黑白格的分布,我们可以推导出,N行N列的棋盘具有二分图性质
//至此,该问题就变成了一个二分图最大匹配求解问题int find(int x, int y) { //匈牙利算法for (int i = 0; i < 4; i++) { //每个点的边指向都确定了,所以可以不建边int a = x + dx[i], b = y + dy[i];if (a <= 0 || b <= 0 || a > n || b > n || g[a][b])continue;//越界或者触碰禁止的格子就不处理PII t = match[a][b];if (st[t.fx][t.fy])continue;//防止多次遍历st[t.fx][t.fy] = true;if (t.fx == 0 || find(t.fx, t.fy)) { //一旦该点没被标记过,或者点曾经的对象可以找到下家match[a][b] = { x,y };return true;//该点就能匹配//搜索时是遍历左子集往右子集的边,但match记录的是右子集点的对象}}return false;
}int main() {cinios;cin >> n >> m;while (m--){int a, b;cin >> a >> b;g[a][b] = true;//点数较小,用邻接矩阵存储方便}int ans = 0;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)if (i + j & 1 && !g[i][j]) { //只对集合一半的点处理匹配,同时不能是障碍mem(st, 0);//每次要重置标记if (find(i, j))ans++;//匹配成功++}cout << ans;return 0;
}
洛谷:矩阵游戏
建图方式:对于 i 行 j 列的1点,建一条 i 连向 j 的边即可,最后跑一个二分图匹配,只有匹配数为 n 才能说明有解
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 210, M = 40010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int h[N], e[M], ne[M], idx;
int match[N << 1];
bool st[N << 1];void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}bool find(int x) { //标准匈牙利for (int i = h[x]; ~i; i = ne[i]) {int j = e[i];if (st[j])continue;st[j] = true;if (!match[j] || find(match[j])) {match[j] = x;return true;}}return false;
}int main() {cinios;cin >> T;while (T--){cin >> n;mem(h, -1);idx = 0;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++) {cin >> k;if (k)add(i, n + j);//行对列建边//虽然二分图是无向图问题,但只用建单向边即可,枚举其中一个集合}mem(match, 0);int mat = 0;for (int i = 1; i <= n; i++) {mem(st, 0);if (find(i))mat++;}if (mat == n)cout << "Yes";//匹配数必须为 nelse cout << "No";cout << '\n';}return 0;
}
——————————————————————————————————————————
二分图最大匹配的一些推论:
由最大匹配推导而来,本文不细节探讨证明(我也不会啊 )
——————————————————————————————————————————
二分图最小点覆盖应用:
证明可得:二分图的最大匹配数 == 最小点覆盖(证明理解不能,寄了)
什么是最小点覆盖?
最小点覆盖并不只在二分图中才存在
在一个图中任意选取 最少 多少个点(两个集合中都可以选!),可以保证图中 所有的边都与选取的点相连
这个数量就是最小点覆盖
Acwing:机械任务
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 110, M = 400010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int match[N];
bool st[N], g[N][N];//证明可得:二分图的最大匹配数 == 最小点覆盖(证明理解不能,寄了)//什么是最小点覆盖?
//最小点覆盖并不只在二分图中才存在,任意一个图中
//选取 最少 多少个点,可以保证图中 所有的边都与选取的点相连
//这个数量就是最小点覆盖bool find(int x) { //标准匈牙利for (int i = 1; i < m; i++)if (!st[i] && g[x][i]) { //确保有边st[i] = true;int t = match[i];if (t == 0 || find(t)) {match[i] = x;return true;}}return false;
}int main() {cinios;//该题就可以转化成一个最小点覆盖问题,然后用二分图最大匹配求解//对于每一个任务 i,可以选择(A 的 a[i] 模式)或(B 的 b[i] 模式)解决////所以在 a[i] 和 b[i] 之间建一条边,代表任务 i(这样的图显然是二分图)//要完成所有任务显然表示要 选取所有的边// //这个问题就可以转化成:最少标记多少个点,即在 a[i] 与 b[i] 中选择其中一个,可以保证图中所有的边都与选取的点相连while (cin >> n, n){cin >> m >> k;mem(g, 0);mem(match, 0);while (k--){int t, a, b;cin >> t >> a >> b;if (!a || !b)continue;//0模式初始就能解决g[a][b] = true;//无向图,但建单向边就可以find了}int ans = 0;for (int i = 1; i < n; i++) {mem(st, 0);if (find(i))ans++;}cout << ans << '\n';}return 0;
}
Acwing:泥地
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 2010, M = 500010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int match[N], r[N][N], c[N][N], rcnt = 1, ccnt = 1;
//记录每个点所在的泥地连续行、连续列,行对列连边,集合自然分为行集合、列集合,满足二分图性质
//最后求的就是,最少的点覆盖所有的边,即最小点覆盖
bool st[N], g[N][N];
string s[60];
//注意一下数组大小bool find(int x) { //标准匈牙利for (int j = 1; j <= ccnt; j++)if (!st[j] && g[x][j]) {st[j] = true;int t = match[j];if (!t || find(t)) {match[j] = x;return true;}}return false;
}int main() {cinios;cin >> n >> m;for (int i = 0; i < n; i++)cin >> s[i];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (j && s[i][j] == '*' && s[i][j - 1] == '.')rcnt++;//一旦遇到干净地面,泥地行编号++if (s[i][j] == '*')r[i][j] = rcnt;//赋予该格行编号}rcnt++;//换行也要++}//对列同样操作,小心bugfor (int i = 0; i < m; i++) { //bug —— i < n, j < mfor (int j = 0; j < n; j++) {if (j && s[j][i] == '*' && s[j - 1][i] == '.')ccnt++;//bug —— s[j][i - 1]if (s[j][i] == '*')c[j][i] = ccnt;//bug —— c[i][j]}ccnt++;}for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)if (s[i][j] == '*') //对于泥地格,建边g[r[i][j]][c[i][j]] = true;int ans = 0;for (int i = 1; i <= rcnt; i++) { //行集合匹配列集合mem(st, 0);if (find(i))ans++;}cout << ans;return 0;
}
——————————————————————————————————————————
二分图最大独立集应用:
最大独立集 是一个点数,指在一个图中选取最多多少个点,可以使得这些点所组成的集合 内部任意两点间没有边
最大独立集 ==(总点数 - 最小点覆盖)
Acwing:骑士放置
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 110, M = 10010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
PII match[N][N];
bool st[N][N], g[N][N];
int dx[] = { -1,1,2,2,1,-1,-2,-2 }, dy[] = { 2,2,1,-1,-2,-2,-1,1 };//最大匹配数 == 最小点覆盖 == 总点数 - 最大独立集
//
//什么是最大独立集?最大独立集 是一个点数,指在一个图中选取最多多少个点,可以使得这些点所组成的集合 内部任意两点间没有边
//
//因此显然,当你把一个图中 最小点覆盖集合 中的点删去(最少的点覆盖所有的边),剩下的点组成的集合就是 最大独立集(总点数 - 最小点覆盖)//该题问最多能放多少个不能互相攻击的骑士,即两点之间的边不可选取,两点之间的联系必须断开
//断开联系也就相当于删去 最小点覆盖bool find(int x, int y) {for (int i = 0; i < 8; i++) { //走日八个方向int ix = x + dx[i], iy = y + dy[i];if (ix <= 0 || iy <= 0 || ix > n || iy > m || g[ix][iy] || st[ix][iy])continue;st[ix][iy] = true;PII t = match[ix][iy];if (t.fx == 0 || find(t.fx, t.fy)) {match[ix][iy] = { x,y };return true;}}return false;
}int main() {cinios;cin >> n >> m >> k;for (int i = 0; i < k; i++){int a, b;cin >> a >> b;g[a][b] = true;}int ans = n * m - k;//点数 == 总点数 减去 不能放骑士的格子for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)if (i + j & 1 && !g[i][j]) {mem(st, 0);if (find(i, j))ans--;//有一个匹配就相当于有一个点覆盖//减去}cout << ans;//就能得到答案return 0;
}
——————————————————————————————————————————
二分图 最大路径点覆盖 与 最大路径重复点覆盖 应用:
最小路径点覆盖含义:
用最少的点,覆盖图中全部的 不相交 路径,这个路径数是多少?
等于总点数 - 最小点覆盖 / 最大匹配数
最小路径点重复覆盖含义:
用最少的点,覆盖图中全部路径(可以有分叉),这个路径数是多少?
等于 对图做一个传递闭包后的 总点数 - 最小点覆盖 / 最大匹配数
Acwing:捉迷藏
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 210, M = 10010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int match[N];
bool st[N], g[N][N];//最小路径点覆盖含义:
//用最少的点,覆盖图中全部的 不相交 路径,这个路径数是多少?
//等于总点数 - 最小点覆盖 / 最大匹配数
//
//最小路径点重复覆盖含义:
//用最少的点,覆盖图中全部路径(可以有分叉),这个路径数是多少?
//等于 对图做一个传递闭包后的 总点数 - 最小点覆盖 / 最大匹配数//此类问题为单向无环图,建二分图比较特殊
//给出的 n 个点作为起点,再虚构 n 个点作为终点,单向边就是左边连右边//连在一条边上的两点显然在一条路径上,这 n 个点中的孤立点就是某路径的终点
//此题要求:选出最多多少个点,保证这些点相互之间都不在同一路径上bool find(int x) {for (int i = 1; i <= n; i++)if (!st[i] && g[x][i]) {st[i] = true;if (match[i] == 0 || find(match[i])) {match[i] = x;return true;}}return false;
}int main() {cinios;cin >> n >> m;while (m--){int a, b;cin >> a >> b;g[a][b] = true;}for (int k = 1; k <= n; k++)//传递闭包for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)g[i][j] |= g[i][k] & g[k][j];//让所有点都尽可能匹配到int res = 0;for (int i = 1; i <= n; i++) {mem(st, 0);if (find(i))res++;}cout << n - res;return 0;
}
——————————————————————————————————————————
二分图(概念、相关算法和题目应用)(全面整理)相关推荐
- 第七篇章——垃圾回收概念及相关算法
垃圾回收--概述 本专栏学习内容来自尚硅谷宋红康老师的视频以及<深入理解JVM虚拟机>第三版 有兴趣的小伙伴可以点击视频地址观看,也可以点击下载电子书 垃圾回收概述 垃圾回收不是Java语 ...
- 【Java】数组Array(概念、相关语法、相关算法)
数组 文章目录 数组 1.数组的相关概念和名词(了解) 2 .数组的相关语法 2.1. 数组的声明 2.2. 数组的初始化 2.3.数组的遍历 2.4. 数组的内存分析 3. 数组的相关算法 3.1. ...
- 《大厂算法面试题目与答案汇总,剑指offer等常考算法题思路,python代码》V1.0版...
为了进入大厂,我想很多人都会去牛客.知乎.CSDN等平台去查看面经,了解各个大厂在问技术问题的时候都会问些什么样的问题. 在看了几十上百篇面经之后,我将算法工程师的各种类型最常问到的问题都整理了出来, ...
- 41.虚拟存储器以及相关算法
虚拟存储器,又有人叫虚拟内存.很容易大家就会把它当做硬件看待. 所以我们先给虚拟存储器定性. 虚拟存储器是计算机系统内存管理的一种技术,它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间 ...
- Algorithm:C++语言实现之链表相关算法(链表相加、链表的部分翻转、链表划分、链表去重、重复元素全部删除)
Algorithm:C++语言实现之链表相关算法(链表相加.链表的部分翻转.链表划分.链表去重.重复元素全部删除) 目录 一.链表 1.1.链表相加 1.2.链表相加 2.1.链表的部分翻转 2.2. ...
- Algorithm:树相关算法(BBT/BST/B树/R树)简介(二叉查找树、二叉查找树的插入节点、二叉查找树的删除、二叉树的遍历、平衡二叉树)C 语言实现
Algorithm:树相关算法(BBT/BST/B树/R树)简介(二叉查找树.二叉查找树的插入节点.二叉查找树的删除.二叉树的遍历.平衡二叉树)C++语言实现 目录 树的基础知识 1.二叉树的遍-前序 ...
- 15-垃圾回收相关算法
垃圾回收相关算法 标记阶段:引用计数算法(Java未使用) 垃圾标记阶段:对象存活判断 在堆里存放着几乎所有的Java对象实例,在GC执行垃圾回收之前,首先需要区分出内存中哪些是存活对象,哪些是已经死 ...
- JVM学习笔记之-拉圾回收概述,垃圾回收相关算法
拉圾回收概述 什么是垃圾 垃圾收集,不是Java语言的伴生产物.早在1960年,第一门开始使用内存动态分配和垃圾收集技术的Lisp语言诞生. 关于垃圾收集有三个经典问题: 哪些内存需要回收? 什么时候 ...
- 图论相关算法理解和总结
晚上学习了一些图论相关算法: 单源最短路径算法: Bellman-Ford 算法: Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shor ...
最新文章
- Element 对象表示 XML 文档中的元素。
- matlab 条形图与面积图
- jquery为图片添加事件
- Spring Cache抽象-基于XML的配置声明(基于ConcurrentMap的配置)
- mysql+影响的行数+获取_我们如何获得受MySQL查询影响的总行数?
- 将Asp.Net页面输出到EXCEL里去
- redis(11)--AOF持久化
- win7 部署tomcat
- Quartz简单实例
- oracle把时间段转换成每一天_在家办公难适应?来看看专职外汇交易员的一天
- java请编写公共类继承抽象类_(Java相关)怎么理解抽象类,继承和接口?
- OC中字符串的提取与替换-四种不同方法实现
- HSPF(Hydrological Simulation Program Fortran)模型应用
- C语言编写猜数字小游戏
- 使用java实现敏感词汇过滤功能
- Linux下Oracle移植数据
- opencv读取透明图片
- MySQL加锁处理分析--何登成
- C++ 数据结构——BF算法
- 百度熊掌号php,百度熊掌号广受站长关注phpcm网站程序的熊掌号页面插件也火了!...