Day1
寒假第一天头必须起好了,冲冲冲
今天熟悉回顾基础算法
二分
回顾基础算法模板,发现了关于二分,我之前是没有看过模板的,基本都是知道二分思想根据题意现写的代码,很容易死循环,现在重新听了Y总讲的模板,发现了自己的一个盲区,关键就是这个l + r >> 1 还是 l + r + 1 >> 1
// 把区间[l, r]分为[l, mid]和[mid + 1, r]时使用
bool check(int x) {...} // check函数
int bisearch_1(int l, int r)
{
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid; // 如果满足check函数要求
else l = mid + 1;
}
return l;
}
// 把区间[l, r]分为[l, mid - 1]和[mid, r]时使用
int bisearch_2(int l, int r)
{
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
使用方法
分析题意,如果mid往后都是满足题意的,那么也就是说mid也是一个可能解,需要把区间更新成[mid, r]那么就是用第二个模板,如果说mid往前都是满足题意的,更新成[l, mid]那么就使用第一个模板即可
离散化
一个预处理的算法,适用于很多数据范围大,数据量小的题
核心步骤:去重 + 排序
sort(alls.begin(), alls.end()) ;
alls.erase(unique(alls.begin(), alls.end()), alls.end()) ;
其次利用结合lower_bound和upper_bound来快速确定元素映射后的位置就即可利用
之前很多图论算法没有好好看,懂思路就跑,现在把代码熟悉下补一补
Kruskal算法
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = 2 * N;
int n, m;
struct node
{
int a, b, c;
}arr[M];
int f[N];
bool cmp(node x, node y)
{
return x.c < y.c;
}
int find(int x)
{
if (x == f[x]) return f[x];
return f[x] = find(f[x]);
}
int main(void)
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) f[i] = i;
for (int i = 0 ; i < m; i++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
arr[i] = {a, b, c};
}
sort(arr, arr + m, cmp);
int res = 0, cnt = 0;
for (int i = 0; i < m; i++) {
if (find(arr[i].a) != find(arr[i].b)) {
res += arr[i].c;
f[find(arr[i].a)] = find(arr[i].b);
cnt++;
}
}
if (cnt < n - 1) puts("impossible");
else printf("%d", res);
return 0;
}
匈牙利算法
我愿称之为牛头人恋爱算法
#include<bits/stdc++.h>
using namespace std;
const int N = 510, M = 100010;
int n, m, k;
int e[M], ne[M], h[N], idx;
int match[N]; // 记录每一个妹子的对象编号
bool st[N];
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 != -1; i = ne[i]) { // 遍历这个男生可以配对的妹子
int j = e[i];
if (!st[j]) { // 如果这个妹子还没被考虑过
st[j] = true;
if (match[j] == 0 || find(match[j])) { // 如果这个妹子还没男朋友或者她的男朋友可以换一个女朋友
match[j] = x; // 更新
return true;
}
}
}
return false; // 实在无法配对
}
int main(void)
{
scanf("%d %d %d", &n, &m, &k);
memset(h, -1, sizeof h);
while (k--) {
int a, b;
scanf("%d %d", &a, &b);
add(a, b);
}
int res = 0;
for (int i = 1; i <= n; i++) {
memset(st, false, sizeof st); // 初始每个妹子还没被考虑
if (find(i)) res ++;
}
printf("%d", res);
return 0;
}