贪心构造+枚举子集+有向图判环

lc3445

无向图当中用一个数组标记每个节点是否访问过,记录这个节点它的父节点,如果一个节点不是fa &&被访问过,就说明环

可以bfs/dfs/union判环

推到有向图 两种状态表示已经无法判定,我们可以用到三色染色法

class Solution {

public:

vector<vector<int>> supersequences(vector<string>& words) {

// 收集有哪些字母,同时建图

int all = 0, mask2 = 0;

vector<int> g[26]{};

for (auto& s : words) {

int x = s[0] - 'a', y = s[1] - 'a';

all |= 1 << x | 1 << y;

if (x == y) {

mask2 |= 1 << x;

}

g[x].push_back(y);

}

// 判断是否有环

auto has_cycle = [&](int sub) -> bool {

int color[26]{};

auto dfs = [&](this auto&& dfs, int x) -> bool {

color[x] = 1;

for (int y : g[x]) {

// 只遍历在 sub 中的字母

if ((sub >> y & 1) == 0) {

continue;

}

if (color[y] == 1 || color[y] == 0 && dfs(y)) {

return true;

}

}

color[x] = 2;

return false;

};

for (int i = 0; i < 26; i++) {

// 只遍历在 sub 中的字母

if (color[i] == 0 && sub >> i & 1 && dfs(i)) {

return true;

}

}

return false;

};

unordered_set<int> st;

int max_size = 0;

// 枚举 mask1 的所有子集 sub

int mask1 = all ^ mask2;

int sub = mask1;

do {

int size = popcount((unsigned) sub);

// 剪枝:如果 size < min_size 就不需要判断了

if (size >= max_size && !has_cycle(sub)) {

if (size > max_size) {

max_size = size;

st.clear();

}

st.insert(sub);

}

sub = (sub - 1) & mask1;

} while (sub != mask1);

vector<vector<int>> ans;

for (int sub : st) {

vector<int> cnt(26);

for (int i = 0; i < 26; i++) {

cnt[i] = (all >> i & 1) + ((all ^ sub) >> i & 1);

}

ans.push_back(cnt);

}

return ans;

}

};

相关推荐
孞㐑¥2 小时前
算法—字符串
开发语言·c++·经验分享·笔记·算法
鱼跃鹰飞2 小时前
Leetcode279:完全平方数
数据结构·算法·leetcode·面试
小龙报2 小时前
【数据结构与算法】单链表核心精讲:从概念到实战,吃透指针与动态内存操作
c语言·开发语言·数据结构·c++·人工智能·算法·链表
long3162 小时前
合并排序 merge sort
java·数据结构·spring boot·算法·排序算法
格林威2 小时前
Baumer相机碳纤维布纹方向识别:用于复合材料铺层校验的 5 个核心技巧,附 OpenCV+Halcon 实战代码!
人工智能·数码相机·opencv·算法·计算机视觉·视觉检测
范纹杉想快点毕业2 小时前
STM32单片机与ZYNQ PS端 中断+状态机+FIFO 综合应用实战文档(初学者版)
linux·数据结构·数据库·算法·mongodb
近津薪荼2 小时前
递归专题(1)——汉诺塔
c++·学习·算法
总斯霖2 小时前
HDU 4857 - 逃生 题解
算法
-To be number.wan2 小时前
算法学习日记 | 模拟
c++·学习·算法