1. 程式人生 > >洛谷P1196

洛谷P1196

題目描述

在這次決戰中,他將巴米利恩星域戰場劃分成30000列,每列依次編號為1, 2, …,30000。之後,他把自己的戰艦也依次編號為1, 2, …, 30000,讓第i號戰艦處於第i列,形成“一字長蛇陣”,誘敵深入。這是初始陣形。當進犯之敵到達時,楊威利會多次釋出合併指令,將大部分戰艦集中在某幾列上,實施密集攻擊。合併指令為M i j,含義為第i號戰艦所在的整個戰艦佇列,作為一個整體接至第j號戰艦所在的戰艦佇列的尾部。顯然戰艦佇列是由處於同一列的一個或多個戰艦組成的。合併指令的執行結果會使佇列增大。 然而,老謀深算的萊因哈特早已在戰略上取得了主動。在交戰中,他可以通過龐大的情報網路隨時監聽楊威利的艦隊調動指令。
在楊威利釋出指令調動艦隊的同時,萊因哈特為了及時瞭解當前楊威利的戰艦分佈情況,也會發出一些詢問指令:C i j。該指令意思是,詢問電腦,楊威利的第i號戰艦與第j號戰艦當前是否在同一列中,如果在同一列中,那麼它們之間佈置有多少戰艦。

輸入樣例#1:

4
M 2 3
C 1 2
M 2 4
C 4 2

輸出樣例#1:

-1
1

分析

對於每個點,分別記錄所屬鏈的頭結點、該點到頭結點的距離以及它所在集合的大小。每次合併將y接在x的尾部,改變y頭的權值和所屬鏈的頭結點,同時改變x的尾節點。
#include<cstdio>
using namespace std;
int father[50000],b[50000],c[50000],n;
int find(int v)
{
    int a;
    if (father[v]==0)
        return v;
    else
    {
        a=find(father[v]);
        b[v]=b[father[v]]+b[v];
        father[v]=a;
        return
father[v]; } } int abs(int p) { if (p<0) return -p; else return p; } int sss(int x,int y) { int l,r; l=find(x);r=find(y); father[l]=r; b[l]=b[l]+c[r]; c[r]=c[l]+c[r]; } int main() { int j,k; char s; for (int i=1;i<=50000;i++) c[i]=1; scanf("%d",&n); for
(int i=1;i<=n;i++) { scanf("%s%d%d",&s,&j,&k); if (s=='M') if (find(j)!=find(k)) sss(j,k); else j=1; else if (find(j)==find(k)) printf("%d\n",abs(b[k]-b[j])-1); else printf("-1\n"); } }