题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=51276
具体题意不描述了,一眼看过去就是并查集,关键是添加边以后更新答案。我是开个二维的数组ans记录答案,vector容器存储直接或间接相连的点(包括本身)。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 6 using namespace std; 7 const int MAXN = 1005; 8 int par[MAXN] , ans[MAXN][MAXN]; 9 vector<int> v[MAXN]; 10 11 void init(int n) { //初始化 12 for(int i = 1 ; i <= n ; i++) { 13 par[i] = i; 14 for(int j = i + 1 ; j <= n ; j++) { 15 ans[i][j] = ans[j][i] = 0; 16 } 17 v[i].clear(); 18 v[i].push_back(i); //清空后加入本身 19 } 20 } 21 22 int Find(int n) { 23 if(n == par[n]) 24 return n; 25 return par[n] = Find(par[n]); 26 } 27 28 int main() 29 { 30 int t , n , m , x , a , b , last , res; 31 scanf("%d" , &t); 32 while(t--) { 33 scanf("%d %d" , &n , &m); 34 init(n); 35 last = 0 , res = n; //res为联通块数 36 for(int ca = 1 ; ca <= m ; ca++) { 37 scanf("%d %d %d" , &x , &a , &b); 38 a = a ^ last , b = b ^ last; 39 int aa = Find(a) , bb = Find(b); 40 if(x == 0) { 41 if(aa != bb) { //不为同一个联通块 42 par[aa] = bb; 43 res--; 44 int xx = v[a].size() , yy = v[b].size(); //预先记录容器大小,不然下面的加点会使size增大 45 for(int i = 0 ; i < xx ; i++) { //更新答案 加点 46 for(int j = 0 ; j < yy ; j++) { 47 ans[v[a][i]][v[b][j]] = ans[v[b][j]][v[a][i]] = ca; 48 v[v[a][i]].push_back(v[b][j]); 49 v[v[b][j]].push_back(v[a][i]); 50 } 51 } 52 } 53 last = res; 54 printf("%d " , last); 55 } 56 else { 57 last = ans[a][b]; 58 printf("%d " , last); 59 } 60 } 61 } 62 }