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;
    }
    


  • 相关阅读:
    c3p0整合mysql报错问题
    MySQL错误问题
    导入项目@Override报错原因及解决办法
    AtomicInteger线程安全的计数器
    jq实现鼠标经过出现上拉菜单
    css实现文字裁切效果
    echarts地图
    css3实现 鼠标经过li时动态画边框(jq库导航)
    仿妙味课堂导航(转)
    jq仿 妙味课堂导航01
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793933.html
Copyright © 2011-2022 走看看