本文最后更新于 2024年7月22日 上午
今日内容:
寻找存在的路径
题目:
给定一个包含 n 个节点的无向图中,节点编号从 1 到 n (含 1 和 n
)。
你的任务是判断是否有一条从节点 source 出发到节点 destination
的路径存在。
输入描述
第一行包含两个正整数 N 和 M,N 代表节点的个数,M 代表边的个数。
后续 M 行,每行两个正整数 s 和 t,代表从节点 s 与节点 t
之间有一条边。
最后一行包含两个正整数,代表起始节点 source 和目标节点
destination。
输出描述
输出一个整数,代表是否存在从节点 source 到节点 destination
的路径。如果存在,输出 1;否则,输出 0。
思路:
并查集模板题,只需要建一个并查集,然后判断source和destination是不是同源。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <bits/stdc++.h> using namespace std;class Union {public : vector<int > f; Union (int n) { f.resize (n); for (int i = 0 ;i < n;i++) { f[i] = i; } } int find (int u) { if (f[u] != u) { return f[u] = find (f[u]); } return f[u]; } void join (int u, int v) { f[find (u)] = find (v); } bool isSame (int u, int v) { return find (u) == find (v); } };int main () { int N, M; cin >> N >> M; Union uf (N + 1 ) ; for (int i = 0 ;i < M;i++) { int a, b; cin >> a >> b; uf.join (a, b); } int s, d; cin >> s >> d; cout << uf.isSame (s, d); return 0 ; }
721. 账户合并
题目:
给定一个列表 accounts
,每个元素 accounts[i]
是一个字符串列表,其中第一个元素 accounts[i][0]
是 名称
(name) ,其余元素是 emails
表示该账户的邮箱地址。
现在,我们想合并这些账户。如果两个账户都有一些共同的邮箱地址,则两个账户必定属于同一个人。请注意,即使两个账户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的账户,但其所有账户都具有相同的名称。
合并账户后,按以下格式返回账户:每个账户的第一个元素是名称,其余元素是
按字符 ASCII 顺序排列 的邮箱地址。账户本身可以以
任意顺序 返回。
示例 1:
1 2 3 4 5 6 7 输入:accounts = [["John" , "johnsmith@mail.com" , "john00@mail.com" ], ["John" , "johnnybravo@mail.com" ], ["John" , "johnsmith@mail.com" , "john_newyork@mail.com" ], ["Mary" , "mary@mail.com" ]] 输出:[["John" , 'john00@mail.com' , 'john_newyork@mail.com' , 'johnsmith@mail.com' ], ["John" , "johnnybravo@mail.com" ], ["Mary" , "mary@mail.com" ]] 解释: 第一个和第三个 John 是同一个人,因为他们有共同的邮箱地址 "johnsmith@mail.com" 。 第二个 John 和 Mary 是不同的人,因为他们的邮箱地址没有被其他帐户使用。 可以以任何顺序返回这些列表,例如答案 [['Mary' ,'mary@mail.com' ],['John' ,'johnnybravo@mail.com' ], ['John' ,'john00@mail.com' ,'john_newyork@mail.com' ,'johnsmith@mail.com' ]] 也是正确的。
思路:
由于今天并查集专题开始,只有一道模板题,所以将前天的力扣每日一题记录,正好也是并查集,提前学过就是快。
给所有的邮箱名编号,方便加入并查集,同时将邮件和名字关联,建立map<email,
name>
根据每个账户的邮箱的编号,为每个账户建立并查集,以每个账户的第一个邮箱作为root
遍历所有的邮箱,建立"邮箱->编号"的映射,实现:能够根据一个邮箱得到邮箱所有者的全部邮箱
得到该邮箱的root编号,建立map<index,
emails >,将该邮箱放入root编号对应的邮箱集中
遍历所有邮箱集,此时邮箱集已经完成合并,排序,通过第一步的邮箱->名字映射得到姓名,合并成一个数组加入答案,并返回。
详见代码注释,可学习其中对于map的遍历简洁写法:auto [e,_] : map
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 class UnionFind {public : vector<int > parent; UnionFind (int n) { parent.resize (n); for (int i = 0 ; i < n; i++) { parent[i] = i; } } void join (int index1, int index2) { parent[find (index1)] = find (index2); } int find (int index) { if (parent[index] != index) { parent[index] = find (parent[index]); } return parent[index]; } };class Solution {public : vector<vector<string>> accountsMerge (vector<vector<string>>& accounts) { map<string, int > emailToIndex; map<string, string> emailToName; int emailIndex = 0 ; for (auto & account : accounts) { string & name = account[0 ]; int size = account.size (); for (int i = 1 ;i < size;i++) { string & email = account[i]; if (!emailToIndex.count (email)) { emailToIndex[email] = emailIndex++; emailToName[email] = name; } } } UnionFind uf (emailIndex) ; for (auto & account : accounts) { string & first = account[1 ]; int root = emailToIndex[first]; int size = account.size (); for (int i = 2 ;i < size;i++) { string & email = account[i]; int index = emailToIndex[email]; uf.join (index, root); } } map<int , vector<string>> indexToEmails; for (auto & [email, _] : emailToIndex) { int index = uf.find (emailToIndex[email]); vector<string>& emails = indexToEmails[index]; emails.emplace_back (email); indexToEmails[index] = emails; } vector<vector<string>> ans; for (auto & [_, emails] : indexToEmails) { sort (emails.begin (), emails.end ()); string & name = emailToName[emails[0 ]]; vector<string> account; account.emplace_back (name); for (auto & email : emails) { account.emplace_back (email); } ans.emplace_back (account); } return ans; } };