题目链接
(略)
(略)
4 4 1
2 1
1 3
3 2
3 4
4 1
0 1 0 1
5 10 0
1 2
1 3
1 4
1 5
3 2
2 4
2 5
4 3
5 3
4 5
0 0 0 0 0
10 9 3
10 1
6 7
8 2
2 5
8 4
7 3
10 9
6 4
5 8
2 6
7 5
3 1
1 3 5 4 3 3 3 3 1 0
题目太冗长了,用markdown慢慢编辑很麻烦,就省略了……
这题比较长,其实不难,就是简单并查集,思路如下:
条件:对某个人 i i i, j j j与之无直接关系,且两者都在集合 f r i e n d s h i p friendship friendship 中
1.用 a n s [ i ] ans[i] ans[i] 数组记录与 i i i 同在集合 f r i e n d s h i p friendship friendship 中且有 b l o c k s h i p blockship blockship 关系的人的数量
2.用 s u m [ i ] sum[i] sum[i] 数组记录集合 f r i e n d s h i p friendship friendship 的元素个数
3.对第 i i i 个人,答案 c n t = s u m [ i ] − a n s [ i ] − 1 cnt=sum[i]-ans[i]-1 cnt=sum[i]−ans[i]−1 ,减1就是减去自身
AC代码如下:
#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
int father[N],sum[N],ans[N];
int n,m,k,x,y;
int Findfather(int x){
return father[x]==x?x:father[x]=Findfather(father[x]);
}
void Union(int a,int b){
a=Findfather(a),b=Findfather(b);
if(a!=b) father[b]=a,sum[a]+=sum[b];
}
void init(){
for(int i=0;i<=n;i++)
father[i]=i,sum[i]=1;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
init();
while(m--){
scanf("%d%d",&x,&y);
ans[x]++,ans[y]++;
Union(x,y);
}
while(k--){
scanf("%d%d",&x,&y);
if(Findfather(x)==Findfather(y)) ans[x]++,ans[y]++;
}
for(int i=1;i<=n;i++){
printf("%d ",sum[Findfather(i)]-ans[i]-1);
}
return 0;
}