【並查集】猜數
阿新 • • 發佈:2018-12-30
【題目描述】
已知一個數列,我會告訴你某兩項的差,然後你要回答我的問題
【輸入格式】
第一行是兩個數 n,m,表示數列有n項,一共有m條指令。
接下來有m行,每行一個指令,指令分兩類:
1. I_i_j_k 表示第i比第j項大k.
2. A_i_j 詢問當前第i項與第j項差的絕對值.('_'表示空格)
【輸出格式】
對於每個2類指令,輸出一行,無法判斷時輸出-1
我們考慮用並查集來維護,我們維護他與根節點的相對大小
對於加法操作,我們先找到他們各自的根節點,如果不同,就對y點的祖先打上標記,因為我們要使x的查詢值比y大z,則應在y的祖先處打上的標記值為
對於詢問操作,若不在並查集則輸出-1,否則輸出相對大小的絕對值差即可
#include<iostream> #include<iomanip> #include<cstring> #include<cmath> #include<cstdio> #include<queue> #include<algorithm> #include<ctime> using namespace std; int n,m,f[10005],fr[10005]; char op[1]; int find(int x) { if(x==f[x]) return x; int fx=find(f[x]); fr[x]+=fr[f[x]]; f[x]=fx; return fx; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) f[i]=i,fr[i]=0; for(int i=1;i<=m;i++) { scanf("%s",op); if(op[0]=='I') { int x,y,z; scanf("%d%d%d",&x,&y,&z); int fx=find(x),fy=find(y); if(fx!=fy) { f[fy]=fx; fr[fy]=fr[x]-fr[y]-z; } } else { int x,y; scanf("%d%d",&x,&y); int fx=find(x),fy=find(y); if(fx!=fy) printf("-1\n"); else printf("%d\n",abs(fr[x]-fr[y])); } } }