刚开始单纯的我写了传统的并查集发现WA了,这是因为传统并查集建的关系是双向的。而本题建立的是单向的关系
比如1给2;2给4,5;3给4;如果传统的并查集,那么3的祖宗节点是1了,显然不符合题意
那么我们再思考发现,如果一个点是祖宗节点,光盘是要给的,还有一种情况是一个点是孤儿,那么这个点是要给光盘的。除此之外的点说明入度(有人给)不为0,那么一定有别人给,追根到底就是祖宗;
对于一个点的入度我们在合并节点的时候统计
还有这题的输入输出,我自己脑抽写了个stirng.getline去做,还要写多位数,直接快排模板叭
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5;
typedef long long LL;
int p[maxn],inn[maxn];
int find(int x)
{
if(x!=p[x]) return p[x]=find(p[x]);
return p[x];
}
inline int read()//快读板子
{
int x = 0, f = 1;
char ch = getchar();
if (ch == '-')
f = -1, ch = getchar();
while(ch<'0'||ch>'9')
ch = getchar();
while(ch<='9'&&ch>='0')
{
x = x * 10 + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int main(void)
{
int n=read();
for(int i=1;i<=n;i++) p[i]=i;
for(int i=1;i<=n;i++)
{
int str=read();
while(str!=0)
{
p[find(str)]=find(i);
inn[str]++;
str=read();
}
}
int sum=0;
for(int i=1;i<=n;i++)
{
if(p[i]==i) sum++;
else if(inn[i]==0) sum++;
}
cout<<sum<<endl;
return 0;
}
并查集会被hack
答案是 2 ,但是并查集做出来的答案是1