寒假:Day1

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值