1. 程式人生 > >POJ-1984-Navigation Nightmare+帶權並查集(中級

POJ-1984-Navigation Nightmare+帶權並查集(中級

sof 走了 Go problem name 更新 討論 nio scan

傳送門:Navigation Nightmare

參考:1:https://www.cnblogs.com/huangfeihome/archive/2012/09/07/2675123.html

參考:2:http://blog.csdn.net/tc_to_top/article/details/43447727

題意:先給出一個四方形的城市地圖的全部信息,

  然後在只知道前k條信息的情況下,詢問a,b之間的距離,若沒連通,輸出-1;

思路:

首先,每次詢問的K是按升序排列的(討論版裏神牛說的,還有就是題號很有深意);

這道題讓我對並查集有一個新的認識:根的代表性是非常強的!並查集裏如果某個節點的改動會影響到整個並查集的所有節點,那麽,在union_set的時候只需要改動根節點就可以了,當然,在find_set函數裏要對所有節點進行更新(這相當於一種延時標記)。我們知道,find_set函數走了兩條路,一條是前往根的路,一條是從跟返回的路,那麽,如果發現根已經被改動,必須在從根返回的路上更新經過的所有節點。這在find_set函數裏是可以實現的。

//樣例
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6 1
1 4 3
2 6 6

模擬一遍樣例,這裏是執行完Find(1-7)以後的坐標
t = 1: x[1] = 0, y[1] = 0
x[6] = 13, y[6] = 0

t = 2: x[1] = 0, y[1] = 0
x[6] = 13, y[6] = 0
x[3] = 22, y[3] = 0

t = 3: x[1] = 0, y[1] = 0
x[6] = 13, y[6] = 0
x[3] = 22, y[3] = 0
x[5] = 22, y[5] = -7

t = 4(換原點):
x[4] = 0, y[4] = 0
x[1] = 0, y[1] = 3
x[6] = 13, y[6] = 3
x[3] = 22, y[3] = 3
x[5] = 22, y[5] = -4

t = 5(換原點):
x[2] = 0, y[2] = 0
x[4] = -20,y[4] = 0
x[1] = -20,y[1] = 3
x[6] = -7, y[6] = 3
x[3] = 2, y[3] = 3
x[5] = 2, y[5] = -4

t = 6: x[2] = 0, y[2] = 0
x[4] = -20,y[4] = 0
x[1] = -20,y[1] = 3
x[6] = -7, y[6] = 3
x[3] = 2, y[3] = 3
x[5] = 2, y[5] = -4
x[7] = -20,y[7] = -2

/*
    帶權並查集;
*/
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;

const int maxn = 40009;
int n,m,fa[maxn],s[maxn],h[maxn];

struct node{
    int a,b,len;
    char c[5];
}mp[maxn];

void init(){
    for(int i=1;i<=n;i++)
        fa[i]
=i; memset(s,0,sizeof(s)); memset(h,0,sizeof(h)); } int ab(int x,int y) { if(x-y>0)return x-y; else return y-x; } int find(int x) { if(fa[x]==x)return x; int tmp = fa[x]; fa[x]=find(fa[x]); h[x] = h[x] + h[tmp]; // 從根回來的路上更新子節點 s[x] = s[x] + s[tmp]; return fa[x]; } void uni(node t,int dx,int dy) { int px = find(t.a); int py = find(t.b); if(px==py)return; fa[px]=py; // 隨意合並 h[px] = h[t.b] - h[t.a] + dx;// 暫且只對根進行偏移 s[px] = s[t.b] - s[t.a] + dy; } int main(){ scanf("%d%d",&n,&m); init(); for(int i=0;i<m;i++) { scanf("%d%d%d%s",&mp[i].a, &mp[i].b, &mp[i].len, mp[i].c); } int q,k=0; scanf("%d",&q); while(q--) { int l,r,e; scanf("%d%d%d",&l,&r,&e); for(int i=k;i<e;i++) { int dx=0,dy=0; switch(mp[i].c[0]) { case N:dy+=mp[i].len;break; case S:dy-=mp[i].len;break; case E:dx+=mp[i].len;break; case W:dx-=mp[i].len;break; } uni(mp[i],dx,dy); } k=e; int pl=find(l),pr=find(r); if(pl!=pr) { puts("-1"); } else { printf("%d\n",ab(h[l],h[r])+ab(s[l],s[r])); } } return 0; }

POJ-1984-Navigation Nightmare+帶權並查集(中級