A1. 道路修建 Small(BNUOJ)

A1. 道路修建 Small

Time Limit: 1000ms
Memory Limit: 131072KB
64-bit integer IO format:  %lld      Java class name:  Main

无向图G初始有n个点,从1n依次标号,但是没有边,

接下来有m次操作,从1m依次标号,你需要对每种操作输出相应的结果,操作分为两种:

输入格式

操作说明

输出结果

0_u_v

加入一条连接标号为u和标号为v的点的边。

输出加边后图G中连通块的个数。

1_u_v

查询标号为u和标号为v的点之间是否连通。

如果连通,输出k,表示最早在第k次操作后标号为u和标号为v的点之间连通,否则输出0

(输入格式中的下划线‘_’表示实际输入文件中的空格)

Input

第一行是一个正整数T(T \leq 5),表示测试数据的组数,

对于每组测试数据,

第一行包含两个整数n(1 \leq n \leq 1000)m(0 \leq m \leq 5000)

接下来m行,每行是3个整数puv,请注意所给的uv均是经过加密的,

解密方式是u=u \ xor \ lastansv=v \ xor \ lastans ,其中lastans表示上一次操作的输出结果,

初始lastans=0,保证p \in \{0,1\},解密后1 \leq u,v \leq nu \ne v

Output

对于每组测试数据,

输出m行,每行包含一个整数,表示操作的输出结果。

Sample Input

1 4 7 0 1 2 1 1 0 0 1 3 0 0 1 1 0 1 0 1 7 1 0 5

Sample Output

3 0 2 2 3 1 6
思路:并查级。
用并查集判断有几个联通块。然后每次加点的时候将不同的两个集合合并到一起时,每个集合里的点相连通的时间最早时间就是此时合并的时间,开个yy数组记录就行了。
 
 
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include< string.h>
  4 #include<stdlib.h>
  5 #include<math.h>
  6 #include<iostream>
  7 #include<vector>
  8 #include<cstdio>
  9  #define sc(x) scanf("%I64d",&x)
 10  #define pr(x) printf("%I64d",x)
 11  #define prr(x) printf(" %I64d",x)
 12  #define prrr(x) printf("%I64d\n",x)
 13 typedef  long  long ll;
 14  const ll N=1e9+ 7;
 15  using  namespace std ;
 16 vector< int>aa[ 1005]; // 记录集合中的点
 17  int bb[ 10005];
 18  int dd[ 10005];
 19  int cc[ 10005]; // 并差集权重数组
 20  int gg[ 10005];
 21  int yy[ 1005][ 1005]; // 记录最早联通的时间
 22  int main( void)
 23 {
 24      int i,j,k,p,q,n,m,s;
 25     scanf( " %d ",&k);
 26      while(k--)
 27     {
 28          for(i= 0; i< 1005; i++)
 29         {
 30             aa[i].clear();
 31             aa[i].push_back(i); // 先将自己加入集合
 32              bb[i]=i;
 33             cc[i]= 1;
 34         }
 35         scanf( " %d %d ",&n,&m);
 36         memset(yy, 0, sizeof(yy));
 37          int nn= 0; // 初始化输出
 38           int ans= 0;
 39          for(i= 1; i<=m; i++)
 40         {
 41             scanf( " %d %d %d ",&s,&p,&q);
 42             p=p^nn;
 43             q=q^nn;
 44              if(s== 0)
 45             {
 46                  int x,y;
 47                  for(x=p; bb[x]!=x;)
 48                 {
 49                     x=bb[x];
 50                 }
 51                  for(y=q; bb[y]!=y;)
 52                 {
 53                     y=bb[y];
 54                 }
 55                  if(x!=y)
 56                 {
 57                     yy[p][q]=i;
 58                     yy[q][p]=i;
 59 
 60                      for(j= 0; j<aa[x].size(); j++)
 61                     {
 62                          for( int  r= 0; r<aa[y].size(); r++)
 63                         {
 64                             yy[aa[x][j]][aa[y][r]]=yy[aa[y][r]][aa[x][j]]=i;
 65 
 66                         }
 67                     } // 记录联通最早的时间,因为他们在此时刚和并
 68                      yy[x][y]=i;
 69                     yy[y][x]=i;
 70                      if(cc[x]>cc[y]) // 合并集合
 71                      {
 72                         cc[x]+=cc[y];
 73                         bb[y]=x;
 74                          for(j= 0; j<aa[y].size(); j++)
 75                         {
 76                             aa[x].push_back(aa[y][j]);
 77                         }
 78                         aa[x].push_back(y);
 79                         aa[y].clear();
 80 
 81                     }
 82                      else
 83                     {
 84                         cc[y]+=cc[x];
 85                         bb[x]=y;
 86                          for(j= 0; j<aa[x].size(); j++)
 87                         {
 88                             aa[y].push_back(aa[x][j]);
 89                         }
 90                         aa[y].push_back(x);
 91                         aa[x].clear();
 92 
 93                     }
 94                 }
 95                  int gh;
 96                  for( int w= 1; w<=n; w++)
 97                 {
 98                      for( gh=w; bb[gh]!=gh;)
 99                     {
100                         gh=bb[gh];
101                     }
102                     gg[w]=gh;
103                 }
104                 sort(gg+ 1,gg+ 1+n); // 判断联通段
105                   int cnt= 1;
106                  for( int h= 2; h<=n; h++)
107                 {
108                      if(gg[h]!=gg[h- 1])
109                     {
110                         cnt++;
111                     }
112                 }
113 
114                 nn=cnt;
115                 printf( " %d\n ",cnt);
116             }
117              else  if(s== 1)
118             {
119                 printf( " %d\n ",yy[p][q]);
120                 nn=yy[p][q];
121             }
122         }
123 
124     }
125      return  0;
126 }

 

 

转载于:https://www.cnblogs.com/zzuli2sjy/p/5180608.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值