拿到这道题马上就想到了最小生成树,对生成树不了解的还是先去看看数据结构吧
生成树的概念就是包含所有顶点的最小连通图,即N个顶点N-1条边连接所有顶点,把每个人看做一个顶点,题意要求的就是让每个顶点都连起来的最大的边,也就是最晚的时间。
最小生成树无非是Prim和Kruskal算法,然后对Prim比较熟悉,就开始无脑写Prim了,写到一半发现并不行。。。
然后改用Kruskal,正好对该算法熟悉一下,其实也比较简单。Kruskal是以边为单位,连接顶点的,那么我们首先对边通过权值(此处为时间)进行排序,然后从最小的边开始,如果符合条件,就把这条边加入进来,最后判断N个顶点,是否有N-1条边,如果不够,说明没能让所有人都结识,返回-1。否则我们找到若干边中最大的,也就是最晚结识的边,作为输出。
class Solution {
public:
int earliestAcq(vector<vector<int>>& logs, int N) {
//克鲁斯卡尔
father=new int[N];
for(int i=0;i<N;i++)
father[i]=-1;
sort(logs.begin(),logs.end(),[](vector<int> v1,vector<int> v2){return v1[0]<v2[0];});
vector<int> path;
for(int i=0;i<logs.size();i++)
{
int findFB=findFather(logs[i][1]);
int findFE=findFather(logs[i][2]);
if(findFB!=findFE)
{
//如果没回路
father[findFB]=findFE;
path.push_back(logs[i][0]);
}
}
if(path.size()<N-1) return -1;
sort(path.begin(),path.end(),[](int i1,int i2){return i1>i2;});
for(auto elem:path)
cout<<elem<<" "<<endl;
return path[0];
}
int findFather(int idx)
{
int cur=idx;
while(father[cur]!=-1)
{
cur=father[cur];
}
return cur;
}
public:
int* father;
};