力扣269周赛的最后一题:题目描述
关于0到n-1,连通性的关键字的问题,很大可能是并查集模板。
定义全局变量:
vector<int> parent; //储存结点的祖先
vector<int> size; //储存以x为祖先的团体的大小
union_set(int n){ //初始化
parent.resize(n);
ranker.resize(n);
for(int i = 0; i < n;++i){
parent[i] = i; //初始每个结点的父节点都是自己
size[i] = 1; //初始每个团体的大小都为1
}
}
查询函数:
int find(int x){
if(parent[x]==x) return x;
parent[x]=find(parent[x]);
return parent[x];
}
连接函数:
bool unionElement(int x,int y){
int fx=find(x),fy=find(y); //查询x和y的祖先
if(fx==fy) return false; //是一个团体里的,不用连接
if(size[fx]<size[fy]) swap(fx,fy); //如果两个不是一个团体的,把小团体合并到大团体里面
parent[fy]=fx; //fy是小团体,fx是大团体,小团体指向大团体
size[fx]+=size[fy]; //fx的数量增加
return true; //合并成功
}
判断是否连接函数:
bool isConnect(int x,int y){
int fx=find(x),fy=find(y); //查找x和y祖先
return fx==fy; //同一个祖先说明是连接的,返回true,反之不连接
}
孤立函数:
bool disConnect(int x){
parent[x]=x; //祖先是自己的结点是孤立的结点或最大父结点
return true;
}
本题需要按照开会时间排序,对数组排序处理。对于相同开会时间的情况,我们的解决办法就是两两连接同一时间开会的专家,会开完之后,孤立所有不知道秘密的专家。
主函数:
bool cmp(const vector<int>&a,const vector<int>&b){
return a[2]<b[2]; //按照从小到大顺序排列
}
vector<int> findAllPeople(int n, vector<vector<int>>& ms, int fp) {
sort(ms.begin(),ms.end(),cmp);
int m=ms.size();
unionElement(0,fp);
for(int i=0;i<m;i++){
int j=i+1;
while(j<m&&ms[j][2]==ms[i][2]) j++;
for(int k=i;k<j;k++){ //处理相同时间开会的专家
unionElement(ms[k][0],ms[k][1]);
}
for(int k=i;k<j;k++){
if(!isConnect(ms[k][0],0)){ //如果不连接的话,孤立两个结点
disConnect(ms[k][0]);
disConnect(ms[k][1]);
}
}
i=j-1;
}
vector<int>ans;
for(int i=0;i<n;i++){
if(isConnect(0,i)) ans.push_back(i);
}
return ans;
}
完整代码:(稍微修改了下)
class Solution {
public:
vector<int> parent; //储存结点的祖先
vector<int> size;
int find(int x){
if(parent[x]==x) return x;
parent[x]=find(parent[x]);
return parent[x];
}
bool unionElement(int x,int y){
int fx=find(x),fy=find(y); //查询x和y的祖先
if(fx==fy) return false; //是一个团体里的,不用连接
if(size[fx]<size[fy]) swap(fx,fy); //如果两个不是一个团体的,把小团体合并到大团体里面
parent[fy]=fx; //fy是小团体,fx是大团体,小团体指向大团体
size[fx]+=size[fy]; //fx的数量增加
return true; //合并成功
}
bool isConnect(int x,int y){
int fx=find(x),fy=find(y); //查找x和y祖先
return fx==fy; //同一个祖先说明是连接的,返回true,反之不连接
}
bool disConnect(int x){
parent[x]=x; //祖先是自己的结点是孤立的结点或最大父结点
return true;
}
static bool cmp(const vector<int>& a,const vector<int>& b){ //需要加static
return a[2]<b[2]; //按照从小到大顺序排列
}
vector<int> findAllPeople(int n, vector<vector<int>>& ms, int fp) {
sort(ms.begin(),ms.end(),cmp);
int m=ms.size();
for(int i=0;i<n;i++){
parent.push_back(i);
size.push_back(1);
}
unionElement(0,fp);
for(int i=0;i<m;i++){
int j=i+1;
while(j<m&&ms[j][2]==ms[i][2]) j++;
for(int k=i;k<j;k++){ //处理相同时间开会的专家
unionElement(ms[k][0],ms[k][1]);
}
for(int k=i;k<j;k++){
if(!isConnect(ms[k][0],0)){ //如果不连接的话,孤立两个结点
disConnect(ms[k][0]);
disConnect(ms[k][1]);
}
}
i=j-1;
}
vector<int>ans;
for(int i=0;i<n;i++){
if(isConnect(0,i)) ans.push_back(i);
}
return ans;
}
};
cmp函数前面需要加static或放在类外面做全局变量,详情见:
Annie Kim’s Blog
以及
initMyHeart’s Blog
又是为困难题流泪的一天。