Loading [MathJax]/jax/output/CommonHTML/jax.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从二进制枚举 follow up 到二分图判定,有点意思

从二进制枚举 follow up 到二分图判定,有点意思

作者头像
ACM算法日常
发布于 2022-02-10 00:59:44
发布于 2022-02-10 00:59:44
40300
代码可运行
举报
文章被收录于专栏:ACM算法日常ACM算法日常
运行总次数:0
代码可运行

这次周赛前三题比较水,第四题看到数据范围想到二进制枚举之后也不难做

不过我在评论区看到有人提到了 T4 对应的 follow-up 题,是 codeforces div2 的 D 题,涉及到了图论建模和二分图判定,一起来看一看吧

涉及知识点:哈希表,二进制枚举,二分图判定

5989. 元素计数

给你一个整数数组 nums,统计并返回在 nums 中同时具有一个严格较小元素和一个严格较大元素的元素数目。

题解

计算所有不等于严格小和严格大的元素个数即可,遍历一遍就行,时间复杂度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// cpp11
class Solution {
public:
    int countElements(vector<int>& nums) {
        int mini = *min_element(nums.begin(), nums.end());
        int maxx = *max_element(nums.begin(), nums.end());
        int ans = 0;
        for (auto& i: nums) {
            if (i > mini && i < maxx) ans++;
        }
        return ans;
    }
};

5991. 按符号重排数组

给定一个下标从 0 开始的整数数组 nums,数组长度 为偶数,由数目相等的正整数和负整数组成

你需要重排 nums 中的元素,使修改后的数组满足下述条件

  • 任意连续的两个整数符号相反
  • 对于符号相同的所有整数,保留它们在 nums 中的顺序
  • 重排后数组以正整数开头。

返回修改后的数组

数据规定

题解

用两个数组存放正数和负数,然后遍历一遍放到答案数组即可,时间复杂度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// cpp11
class Solution {
public:
    vector<int> rearrangeArray(vector<int>& nums) {
        vector<int> pos, neg;
        for (auto& i: nums) {
            if (i > 0) pos.push_back(i);
            else neg.push_back(i);
        }
        int n = static_cast<int>(pos.size());
        vector<int> ans;
        for (int i = 0; i < n; ++i) {
            ans.push_back(pos[i]);
            ans.push_back(neg[i]);
        }
        return ans;
    }
};

5990. 找出数组中的所有孤独数字

给定一个长度为 的整数数组,请你返回数组中所有只出现了一次,且相邻数都不在数组中的元素数据规定

题解

直接哈希表模拟即可,时间复杂度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// cpp11
class Solution {
public:
    vector<int> findLonely(vector<int>& nums) {
        unordered_map<int, int> mp;
        for (auto& i: nums) mp[i]++;
        vector<int> ans;
        for (auto& i: nums) if (mp[i] == 1 && !mp[i - 1] && !mp[i + 1]) ans.push_back(i);
        return ans;
    }
};

5992. 基于陈述统计最多好人数

给定 个人,可能是好人也可能是坏人,好人一定说真话,坏人不一定说真话

每个人都对另外 个人有一个陈述,分别为

  • 表示坏人
  • 表示好人
  • 表示不了解于是我们得到一个 的矩阵,表示各个陈述,根据这个陈述表格,请你计算好人的最大可能的数量

数据规定

题解

这个数据范围一看就是进制枚举,一开始看错题目了,以为坏人的陈述要么全真要么全假,于是弄了三进制枚举,结果 wa

事实上,坏人的每一条陈述都可能为真,也可能为假,但是好人的每一条陈述一定为真,所以我们根据好人的陈述来判断就行

考虑二进制枚举,枚举每个人为好人的情况,然后根据好人的陈述判断枚举是否自洽,枚举的过程维护好人的最大值即可,时间复杂度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// cpp11
class Solution {
public:
    int maximumGood(vector<vector<int> >& sta) {
        int n = static_cast<int>(sta.size());
        int ans = 0;
        for (int i = 0; i < (1 << n); ++i) {
            bool flag = true;
            int cnt = 0;
            for (int j = 0; j < n; ++j) {
                if ((i >> j) & 1) {  // j 是好人
                    for (int k = 0; k < n; ++k) {
                        if (sta[j][k] == 2) continue;
                        if (sta[j][k] != ((i >> k) & 1)) {
                            flag = false;
                            break;
                        }
                    }
                    ++cnt;
                }
                if (!flag) break;
            }
            if (flag) ans = max(ans, cnt);
        }
        return ans;
    }
};

「T4 follow up」 如果坏人说的话一定为假呢?

给定 个人,和 条关系,每一条关系由 组成,表示 是好人/坏人,

  • 如果 是好人,那么他说的话一定为真话
  • 如果 是坏人,那么他说的话一定为假话

根据这 条陈述计算最大的好人数量,如果陈述有矛盾,输出 数据规定

题解

我们发现

  • 如果 是坏人,那么无论 是好人还是坏人,他和 的身份一定不同
  • 如果 是好人,那么无论 是好人还是坏人,他和 的身份一定相同

我们可以根据上面的观察建图

  • 如果 是坏人,那么 直接连边
  • 否则设置一个中间点 ,将 以及 连接起来

由此我们可以得到一张含有多个强连通分量的图,我们对图上每一个强连通分量做二分图判定即可

二分图判定可以在 dfs 的过程用黑白染色算法来做

对于每一个强连通分量,如果二分图判定失败,那么意味着整体矛盾,答案输出

否则我们将每一个二分图中较多的那一块置为好人,求和即可,时间复杂度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// cpp11
#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 7;
const int M = 5e5 + 7;
int t, n, m, flag, fake;
vector<int> c(2), color(N + M);
unordered_map<int, vector<int>> g;

void dfs(int u) {
    c[color[u]] += (u <= n);
    for (auto &i: g[u]) {
        if (color[i] == -1) {
            color[i] = color[u] ^ 1, dfs(i);
        }
        else if (color[i] == color[u]) {
            flag = 1;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin >> t;
    while (t--) {
        cin >> n >> m;
        g.clear();
        for (int i = 0; i <= n + m; ++i) color[i] = -1;
        flag = 0, fake = n + 1;
        for (int i = 1; i <= m; ++i) {
            int a, b;
            string type;
            cin >> a >> b >> type;
            if (type == "imposter") {
                g[a].push_back(b);
                g[b].push_back(a);
            } else {
                g[a].push_back(fake);
                g[fake].push_back(a);
                g[b].push_back(fake);
                g[fake].push_back(b);
                fake++;
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            if (color[i] == -1) {
                color[i] = 0;
                c[0] = 0, c[1] = 0;
                dfs(i);
                ans += max(c[0], c[1]);
            }
        }
        if (flag) ans = -1;
        cout << ans << endl;
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
LeetCode周赛277场,10分钟A三题,第四题翻车了……
不知道大家有没有注意到题目的坑点,题目中说的是一个严格较小和较大的元素,说了严格较小,但没有说是严格一个。其实题目的意思是至少有一个,也就是说多于一个也OK,但偏偏样例当中无法体现……
TechFlow-承志
2022/09/22
2240
LeetCode周赛277场,10分钟A三题,第四题翻车了……
UVA 11080 – Place the Guards(二分图判定)
题意:一些城市。之间有道路相连,如今要安放警卫,警卫能看守到当前点周围的边,一条边仅仅能有一个警卫看守,问是否有方案,假设有最少放几个警卫
全栈程序员站长
2022/07/07
1750
LeetCode 2151. 基于陈述统计最多好人数(状态压缩)
给你一个下标从 0 开始的二维整数数组 statements ,大小为 n x n ,表示 n 个玩家对彼此角色的陈述。
Michael阿明
2022/03/10
4110
LeetCode 2151. 基于陈述统计最多好人数(状态压缩)
HDU 2444 The Accomodation of Students(二分图判断+最大匹配数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2444        题意是有n个人,m个配对,问能不能根据m个将这些人分成两个集合,且集合中的任意两人
Ch_Zaqdt
2019/01/11
5980
C++ 图进阶系列之剖析二分图的染色算法和匈牙利算法
二分图的定义已经说明,图中存在二个独立的子集,为了区分这两个子集,可以给其中一个子集中的顶点染上红色,另一个子集中的顶点染上蓝色。具体是什么颜色并不重要,只要能区分就可以。
一枚大果壳
2023/08/18
5600
C++ 图进阶系列之剖析二分图的染色算法和匈牙利算法
二分图匹配详解
二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)G=(V,E)是一个无向图。如顶点集VV 可分割为两个互不相交的子集,并且图中每 条边依附的两个顶点都分属两个不同的子集。则称图GG 为二分图。我们将上边顶点集合称 为XX 集合,下边顶点结合称为YY 集合,如下图,就是一个二分图。
风骨散人Chiam
2020/10/28
1K0
二分图匹配详解
HDU 5971 Wrestling Match(二分图染色)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5971        题意是有n个人,m个匹配,x个good player,y个bad player,每
Ch_Zaqdt
2019/01/11
4560
上分掉分,不过一念之间罢
现在可以在空地放水桶,位置 i 的水桶可以服务 i - 1, i + 1 位置的房屋
ACM算法日常
2021/12/06
4950
蔚来的题,偏思维,有点意思!
蔚来汽车联名力扣周赛的题目涉及的算法都很常见,但是都带了一点思维,作为头脑风暴是个不错的选择。
ACM算法日常
2021/12/28
7710
HDU 4185 Oil Skimming(思维+二分图最大匹配数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4185        题意是输入n*n的地图,然后问最多有多少个1*2或者2*1的'#'。      
Ch_Zaqdt
2019/01/11
4230
最全二分图总结(最大匹配、最大权匹配、点覆盖、独立集、路径覆盖,带证明和例题)
二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。(简单说就是把一个图的顶点分成两个集合,且集合内的点不邻接)
Here_SDUT
2022/06/29
5.1K0
最全二分图总结(最大匹配、最大权匹配、点覆盖、独立集、路径覆盖,带证明和例题)
算法基础学习笔记——⑫最小生成树\二分图\质数\约数
罗列出每个数,依次删除每个数的倍数,剩下的数就是质数,可以对此进行优化,可以不删每一个数的倍数, 可以只删质数的倍数,这样就不用重复删。
命运之光
2024/03/20
1160
算法基础学习笔记——⑫最小生成树\二分图\质数\约数
BZOJ1562: [NOI2009]变换序列(二分图 匈牙利)
30%的数据中N≤50; 60%的数据中N≤500; 100%的数据中N≤10000。
attack
2018/07/27
2570
BZOJ1562: [NOI2009]变换序列(二分图 匈牙利)
二分图详解
       本篇博客主要讲解什么是二分图,怎样判断二分图,匈牙利算法和HK(Hopcroft-Karp)算法,以及二分图多重匹配。
Ch_Zaqdt
2019/01/10
2.4K0
POJ3279 (二进制枚举)
Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which is colored black on one side and white on the other side.
dejavu1zz
2020/10/23
5580
BZOJ1191: [HNOI2006]超级英雄Hero(二分图匹配)
现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的
attack
2018/07/27
2630
东哥带你刷图论第四期:二分图的判定
除此之外,并查集算法计算连通分量 也是一个常用的图论算法,名流问题 也和图结构有一些相关性。
labuladong
2021/11/09
6640
Wannafly挑战赛27 B- 紫魔法师(二分图判断)
题目链接:https://ac.nowcoder.com/acm/contest/215/B
Ch_Zaqdt
2019/01/11
3510
二分图判定(图的搜索)
     给定一个具有n个顶点的图。要给图上每个顶点染色,并且要使相邻的顶点颜色不同。问是否能最多用2种颜色进行染色?题目保证没有重边和自环。
砖业洋__
2023/05/06
1740
二分图判定(图的搜索)
洛谷P2764 最小路径覆盖问题(二分图)
题意 给出一张有向无环图,求出用最少的路径覆盖整张图,要求路径在定点处不相交 输出方案 Sol 定理:路径覆盖 = 定点数 - 二分图最大匹配数 直接上匈牙利 输出方案的话就不断的从一个点跳匹配边 #include<cstdio> #include<queue> #include<cstring> using namespace std; const int MAXN = 1e5 + 10, INF = 1e9 + 10; inline int read() { char c = getchar()
attack
2018/07/27
6550
相关推荐
LeetCode周赛277场,10分钟A三题,第四题翻车了……
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验