zoukankan      html  css  js  c++  java
  • 【NOI2002T1】银河英雄传说-并查集

    测试地址

    题目大意:有30000艘战舰依次排成30000列,以1~30000编号,有2种操作:1.M i j:将i号战舰所在的列作为一个整体接到j号战舰所在列的尾部。2.C i j:如果i号战舰和j号战舰在同一列,询问它们之间有多少艘战舰,否则输出-1。根据询问给出正确的答案。

    做法:用head[i]记录i号战舰所在列的最前端的战舰序号,len[i]记录以i号战舰为最前端的列的长度,dist[i]记录i号战舰到它所在列的最前端的战舰的距离。M操作实际上就是合并操作,在合并时注意维护这几个值。x,y间的战舰数量就是abs(dist[x]-dist[y])-1。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    long t,dist[30010]={0},head[30010]={0},len[30010]={0};
    char c;
    
    long find(long x)
    {
      long r=x,i,j,next;
      while(head[r]!=r) r=head[r];
      i=x;
      while(i!=r)
      {
        next=head[i];
        head[i]=r;
    	j=next;
    	while(j!=r)
    	{
    	  dist[i]+=dist[j];
    	  j=head[j];
    	}
    	i=next;
      }
      return r;
    }
    
    void merge(long a,long b)
    {
      long fa=find(a),fb=find(b);
      head[fa]=fb;
      dist[fa]+=len[fb];
      len[fb]+=len[fa];
    }
    
    int main()
    {
      scanf("%ld
    ",&t);
      for(int i=1;i<=30000;i++)
      {
        head[i]=i;
    	len[i]=1;
    	dist[i]=0;
      }
      
      for(int i=1;i<=t;i++)
      {
        long x,y;
        scanf("%c %ld %ld
    ",&c,&x,&y);
    	if (c=='M') merge(x,y);
    	if (c=='C')
    	{
    	  long fx=find(x),fy=find(y);
    	  if (fx!=fy) printf("-1
    ");
    	  else printf("%ld
    ",abs(dist[x]-dist[y])-1);
    	}
      }
      
      return 0;
    }
    


  • 相关阅读:
    USACO Grass Planting
    洛谷 P3178 [HAOI2015]树上操作
    史上最全NOIP初赛知识点
    史上最全的CSP-J/S 第一轮知识点
    洛谷 P1886 滑动窗口
    背包九讲—简单背包
    NOIP 2005 采药
    洛谷 P2357 守墓人
    NOI 2015 软件包管理器
    洛谷 P3384 【模板】树链剖分
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793933.html
Copyright © 2011-2022 走看看