题目难度:两颗半星
题目大意:给出不同的图片,每个图片都有鸟,问最多会有多少棵树,然后最多有多少鸟,认为一张图片中的鸟都是一棵树上的。
题目坑点:就是并查集,但是需要优化一下并查集的查找的函数,需要对过程中的节点保存一下,然后最后再挨个加在最后的父节点上。这样可以明显的优化时间复杂度,没有优化之前,改了所有的cin,cout,然后勉强145ms通过,优化了并查集之后,仅需要十几毫秒。。。可怕的优化。
代码如下:
#include<iostream>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<map>
#include<cstring>
#define MAX 11000
using namespace std;
int parent[MAX];
int Find(int n){
vector<int> v;
while(parent[n]!=-1){
v.push_back(n);
n=parent[n];
}
for(int i=0;i<v.size();i++)
parent[v[i]]=n;
return n;
}
void Union(int a,int b){
int fa=Find(a),fb=Find(b);
if(fa!=fb)
parent[fa]=fb;
}
int main(){
fill(parent,parent+MAX,-1);
int N,maxNum=0;
scanf("%d",&N);
for(int i=0;i<N;i++){
int num,na,nb;
scanf("%d",&num);
if(num==0){
continue;
}
else{
scanf("%d",&na);
if(na>maxNum)
maxNum=na;
for(int j=1;j<num;j++){
scanf("%d",&nb);
if(nb>maxNum)
maxNum=nb;
Union(na,nb);
}
}
}
int trees=0;
for(int i=1;i<=maxNum;i++){
if(parent[i]==-1)
trees++;
}
printf("%d %d\n",trees,maxNum);
int Q,qa,qb;
scanf("%d",&Q);
for(int i=0;i<Q;i++){
scanf("%d%d",&qa,&qb);
if(Find(qa)==Find(qb))
printf("Yes\n");
else
printf("No\n");
}
}