CODEVS 1540 銀河英雄傳說(並查集)

                                1540 銀河英雄傳說

題目鏈接:http://codevs.cn/problem/1540/

題目描述 Description

公元五八一年,地球居民遷移至金牛座α第二行星,在那裏發表銀河聯邦創立宣言,同年改元爲宇宙曆元年,並開始向銀河系深處拓展。

    宇宙歷七九九年,銀河系的兩大軍事集團在巴米利恩星域爆發戰爭。泰山壓頂集團派宇宙艦隊司令萊因哈特率領十萬餘艘戰艦出征,氣吞山河集團點名將楊威利組織麾下三萬艘戰艦迎敵。

    楊威利擅長排兵佈陣,巧妙運用各種戰術屢次以少勝多,難免恣生驕氣。在這次決戰中,他將巴米利恩星域戰場劃分成30000列,每列依次編號爲1, 2, …, 30000。之後,他把自己的戰艦也依次編號爲1, 2, …, 30000,讓第i號戰艦處於第i(i = 1, 2, …, 30000),形成“一字長蛇陣”,誘敵深入。這是初始陣形。當進犯之敵到達時,楊威利會多次發佈合併指令,將大部分戰艦集中在某幾列上,實施密集攻擊。合併指令爲M i j,含義爲讓第i號戰艦所在的整個戰艦隊列,作爲一個整體(頭在前尾在後)接至第j號戰艦所在的戰艦隊列的尾部。顯然戰艦隊列是由處於同一列的一個或多個戰艦組成的。合併指令的執行結果會使隊列增大。

    然而,老謀深算的萊因哈特早已在戰略上取得了主動。在交戰中,他可以通過龐大的情報網絡隨時監聽楊威利的艦隊調動指令。

    在楊威利發佈指令調動艦隊的同時,萊因哈特爲了及時瞭解當前楊威利的戰艦分佈情況,也會發出一些詢問指令:C i j。該指令意思是,詢問電腦,楊威利的第i號戰艦與第j號戰艦當前是否在同一列中,如果在同一列中,那麼它們之間佈置有多少戰艦。

    作爲一個資深的高級程序設計員,你被要求編寫程序分析楊威利的指令,以及回答萊因哈特的詢問。

    最終的決戰已經展開,銀河的歷史又翻過了一頁……

輸入描述 Input Description

輸入文件galaxy.in的第一行有一個整數T1<=T<=500,000),表示總共有T條指令。

以下有T行,每行有一條指令。指令有兩種格式:

1.        M  i  j  :ij是兩個整數(1<=i , j<=30000),表示指令涉及的戰艦編號。該指令是萊因哈特竊聽到的楊威利發佈的艦隊調動指令,並且保證第i號戰艦與第j號戰艦不在同一列。

2.        C  i  j  :ij是兩個整數(1<=i , j<=30000),表示指令涉及的戰艦編號。該指令是萊因哈特發佈的詢問指令。

輸出描述 Output Description

輸出文件爲galaxy.out。你的程序應當依次對輸入的每一條指令進行分析和處理:

如果是楊威利發佈的艦隊調動指令,則表示艦隊排列發生了變化,你的程序要注意到這一點,但是不要輸出任何信息;

如果是萊因哈特發佈的詢問指令,你的程序要輸出一行,僅包含一個整數,表示在同一列上,第i號戰艦與第j號戰艦之間佈置的戰艦數目。如果第i號戰艦與第j號戰艦當前不在同一列上,則輸出-1

樣例輸入 Sample Input

4

M 2 3

C 1 2

M 2 4

C 4 2

樣例輸出 Sample Output

-1

1

數據範圍及提示 Data Size & Hint

 

第一列

第二列

第三列

第四列

&hellip;&hellip;

初始時

1

2

3

4

&hellip;&hellip;

M 2 3

1

 

3

2

4

&hellip;&hellip;

C 1 2

1號戰艦與2號戰艦不在同一列,因此輸出-1

M 2 4

1

 

 

4

3

2

&hellip;&hellip;

C 4 2

4號戰艦與2號戰艦之間僅佈置了一艘戰艦,編號爲3,輸出1

題解:每次合成爲一列,與查詢兩個戰艦中間的戰艦個數,帶權並查集的模板題,給邊權計爲1即可,wa了幾次發現是數組越界,CODEVS上的數組越界不是CE是WA。。

AC代碼:

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 30005;
int n,fa[maxn],d[maxn],size[maxn];
int find(int k)
{
    if (fa[k] != k)
    {
        int f = find(fa[k]);
        d[k] += d[fa[k]];
        fa[k] = f;
    }
    return fa[k];
}
void intc()
{
    _for(i,1,maxn-2)fa[i]=i;
    _for(i,1,maxn-2)size[i]=1;
}
int main(int argc, char const *argv[])
{
    cin>>n;
    intc();
    while(n--)
    {
        char s[2];
        int x,y;
        cin>>s;
        cin>>x>>y; 
        int p = find(x);
        int q = find(y);
        if(s[0]=='M')
        {
            fa[p]=q;
            d[p]=size[q];
            size[q]+=size[p];
        }
        else
        {
            if(p!=q)cout<<"-1"<<endl;
            else cout<<abs(d[x]-d[y])-1<<endl;
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章