題目
一幅畫裏面的鳥爲同一棵樹上的,問有多少棵樹和多少隻鳥,以及對於兩隻鳥判斷是否在同一個樹上~
輸入第一行爲N,接下來有N行
這N行中,第一個是這幅畫(這棵樹)裏面的鳥的數量K,接下來是這K個鳥的編號。輸出有多少棵樹,多少隻鳥。
接着,輸入Q,表示詢問的個數。
接下來的Q行,有兩個鳥的編號,問你這兩個鳥是不是在同一幅畫(一棵樹)中。
分析
躺屍很多天。。。
並查集選擇使用了遞歸寫法。
int ffind(int a)
{
if( a != pre[a])
{
pre[a] = ffind(pre[a]);
}
return pre[a];
}
但是要注意這種寫法中,
if(exist[i]) //cout << i << " " << pre[i] << endl;
{
int root = ffind(i);
cnt[root] ++;
//cout << i << " " << root << endl;
}
這兩個地方cout的結果是不同的。遞歸寫法需要再一次壓縮路徑。
代碼
const int maxn = 1e4 + 10;
int pre[maxn];
int exist[maxn];
int cnt[maxn];
int ffind(int a)
{
if( a != pre[a])
{
pre[a] = ffind(pre[a]);
}
return pre[a];
}
int main()
{
for(int i = 0 ; i < maxn ; i ++)
pre[i] = i;
int N ; cin >> N;
for(int i = 0 ; i < N ; i ++)
{
int K ; cin >> K;
int st ; cin >> st; exist[st] = 1;
for(int i = 0 ; i < K - 1 ; i ++)
{
int ed ; cin >> ed; exist[ed] = 1;
int prest = ffind(st);
int preed = ffind(ed);
if(prest != preed)
{
pre[prest] = preed;
}
}
}
for(int i = 1 ; i < maxn ; i ++)
{
if(exist[i]) //cout << i << " " << pre[i] << endl;
{
int root = ffind(i);
cnt[root] ++;
//cout << i << " " << root << endl;
}
}
int numtree = 0 , numbird = 0;
for(int i = 1 ; i < maxn ; i ++)
{
if(exist[i] && cnt[i])
{
numtree ++;
numbird += cnt[i];
}
}
cout << numtree << " " << numbird << endl;
int Q ; cin >> Q;
for(int i = 0 ; i < Q ; i ++)
{
int a , b;
cin >> a >> b;
if(ffind(a) != ffind(b))
cout << "No" << endl;
else cout << "Yes" << endl;
}
}