正文

Zoj 2833 Friendship2008-01-22 18:40:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/cruxd/32353.html

分享到:

2730205 2008-01-22 18:15:30 Accepted 2833 C++ 00:00.95 1180K C.D.   这大概就是所谓的RPWT,拿出来炫耀一下。【灰溜溜爬开】 其实这题的时限是3000ms,还宽裕的很。但前十名都能把时间压到500ms以内,说明普通的并查集还有值得优化的地方。顺便讲一句,这题通过的人数好X多。第一次写的时候根本就忘了什么是压缩路径,可耻地TLE鸟。【= =】 发现上一次写并查集是一年前的事情,结果又忘记怎么做了……【为什么是又】 所谓的并查集,也只不过是一枚特殊的树罢了。这棵树在完成findset操作之后,高度至多为2,而且形式为根节点下面N个叶子——这就是压缩;在完成两棵树的合并之后高度至多为3.为了方便编写,采用的是数组而不是链表;这一点我倒是牢牢记住了。 /* zoj 2833 author : Crux.D date : 2008.1.21 description : unionset*/ #include <cstdio>#include <string> int parent[100001], num[100001], N, M, cs = 0; void init (){ int i; for ( i = 0; i <= N; i ++ ) {  parent[i] = -1;  num[i] = 1; } if ( cs ++ )  printf ( "\n" ); printf ( "Case %d:\n", cs );} int find_set ( int n ){ //寻找树的根节点 int pre = n; while ( parent[pre] != -1 ) {  pre = parent[pre]; } int root = pre; //非递归从底到顶压缩路径,简化为高度为2的树 while ( n != root ) {  int t = parent[n];  parent[n] = root;  n = t; } return root;  }  int union_set ( int n1, int n2 ){ int t1 = find_set ( n1 ); int t2 = find_set ( n2 ); //合并之后树的高度为3,小树合至大树 if ( t1 == t2 )   return 0; if ( num[t1] < num[t2] ) {  parent[t1] = t2;  num[t2] += num[t1]; } else {  parent[t2] = t1;  num[t1] += num[t2]; } return 0;} void query_friend ( int n ){ int t = find_set ( n ); printf ( "%d\n", num[t] );} int main (){ //freopen ( "in.txt", "r", stdin );  while ( scanf ( "%d %d ", &N, &M ) != EOF ) {  int i;  init ();  for ( i = 0; i < M; i ++ )  {      char ch;   int t1, t2 = 0;   scanf ( "%c", &ch );   if ( ch == 'M' )   {    scanf ( "%d %d ", &t1, &t2 );    union_set ( t1, t2 );   }   else   {    scanf ( "%d ", &t1 );    query_friend ( t1 );   }   //pt ();   //printf ( "%c %d %d\n", ch, t1, t2 );  }   }  return 0;}

阅读(3119) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册