考察:并查集的基本应用
想到了再建一个敌人数组,但没想到怎么操作...菜是原罪
正确思路:
如果是朋友,我们直接并入一个集合
如果是敌人,我们需要建立一个N叉树,分支是敌人数组的下标,里面的值是根,比如e[5] = 1,表示根为1,分支为5的树,n次操作后,我们会形成一个n叉树,此时我们需要将这些分支全部并入朋友数组,像上题的传染病的解法,将1号分支作为并入对象,每个分支依次与它合并,这样最后就会并入朋友数组中
1 #include <iostream> 2 using namespace std; 3 const int N = 1010; 4 int p[N],e[N],ans,vis[N]; 5 int find(int x) 6 { 7 if(p[x]!=x) p[x]=find(p[x]); 8 return p[x]; 9 } 10 void merge(int x,int y) 11 { 12 p[find(p[x])] = find(y); 13 } 14 int main() 15 { 16 int n,m; 17 char op[2]; 18 scanf("%d%d",&n,&m); 19 for(int i=1;i<=n;i++) p[i] = i; 20 while(m--){ 21 int x,y; 22 scanf("%s%d%d",op,&x,&y); 23 if(op[0]=='E'){ 24 if(!e[x]) e[x] = y; 25 if(!e[y]) e[y] = x; 26 merge(e[x],y); 27 merge(e[y],x); 28 }else merge(x,y); 29 } 30 for(int i=1;i<=n;i++){ 31 if(!vis[find(i)]) ans++; 32 vis[find(i)] =1; 33 } 34 printf("%d\n",ans); 35 return 0; 36 }