C11BC2 spoj – Robin

Nguồn đề bài: http://vn.spoj.com/problems/C11BC2/

1. Đề bài C11BC2 spoj

Một ngày đẹp trời nọ, trên vương quốc của các Coders 2011, bỗng xuất hiện 1 lão phù thủy độc ác, lão phù thủy sirDat_LS đã có âm mưu thôn tính đất nước  của đức vua vodanh9x. Lão phù thủy này rất yêu con gái của đức vua là Rose và đã bắt Rose về nơi ở của lão ta.

Đức vua vodanh9x liền tìm hiệp sĩ Robin và sẽ hứa gả con gái cho Robin nếu chàng cứu được công chúa Rose trở về. Lão phù thủy sirDat_LS độc ác với khuôn mặt rất ghê tởm khiến công chúa mỗi khi nhìn thấy hắn thì công chúa lại ngất đi.

Và rồi, chàng Robin của chúng ta đã tìm được đến nơi ở của lão phù thủy. Nơi ở của lão là 1 mê cung có N phòng, và N phòng này liên thông với nhau và có đúng N-1 đường đi (coi mỗi đường đi là 1 cạnh).

Nhưng khó khăn thay, lão phù thủy đã đánh số mỗi đường đi là 1 hoặc 2. Nếu chàng Robin muốn đến cứu công chúa, thì từ nơi xuất phát đến nơi có công chúa phải có ít nhất một đường đi được đánh số 2, nếu không chàng Robin sẽ chết.

Yêu cầu: Cho m truy vấn (m <= 10^5) mỗi truy vấn có dạng (x,y), trong đó x là nơi xuất phát của Robin và y là nơi nhốt công chúa. Xác định đường đi ngắn nhất từ x đến y có cạnh co trọng số 2 hay không.

Input

Dòng đầu là số nguyên N (N <= 10^4) – số đỉnh của đồ thị và M  – số truy vấn.

Từ dòng 2 đến dòng N: dòng thứ i chứa 2 số nguyên dương  x (x < i) và k (k <= 2) nghĩa là có cạnh nối giữa i và x và được đánh số là k.

M dòng sau: mỗi dòng chứa 2 số x và y (Biểu thị cho truy vấn (x,y)).

Output

Với mỗi truy vấn, xuất ra “YES” nếu tồn tại đường đi có ít nhất 1 cạnh có trọng số 2, ngược lại xuất ra “NO”.

Example

Input:
6 7
1 1
1 2
3 1
1 2
5 2
1 3
5 1
2 1
2 1
1 2
2 4
1 2
Output:
YES
YES
NO
NO
NO
YES
NO

2. Thuật Toán C11BC2 spoj

a. Nhận Xét

Robin đi từ x đến y có đi qua cạnh số 2. Tức là nếu không cho RoBin đi qua cạnh số 2 thì Robin không thể đi đến y được (vì đề bài cho có N-1 cạnh). Như vậy bài toán được đưa về mô hình kiểm tra liên thông.

b. Hướng dẫn

– chỉ đọc các cạnh 1 vào đồ thị, còn các cạnh 2 ta sẽ bỏ.

– Xây dựng mảng DD[i] là chỉ số vùng liên thông của đỉnh i. Xây dựng mảng này bằng thuật toán BFS hoặc DFS.

– Trả lời các truy vấn: Nếu DD[x]<>DD[y] thì kết quả là YES (bởi vì khi ta bỏ cạnh 2 ra, mà ko thể đi từ x đến y thì dễ dàng suy ra đồ thị ban đầu nếu đi từ x đến y sẽ đi qua cạnh 2). Ngược lại là NO.

3. Code tham khảo bài C11BC2 spoj

const   fi='';
        nmax=10000;
type    data=longint;
var
        f:text;
        n,m:data;

        head:array[0..nmax+1] of word;
        canhx,canhy,adj:array[1..nmax*2] of word;
        spt:data;
        DD:array[0..nmax+1] of data;
        count:data;

procedure dfs(u:data);
var     v:data;
begin
        dd[u]:=count;
        for v:=head[u]+1 to head[u+1] do
                if dd[adj[v]]=0 then
                        dfs(adj[v]);
end;

procedure docfile;
var     i,j,x,k:data;
begin
        readln(f,n,m);
        spt:=0;
        for i:=2 to n do
                begin
                        readln(f,j,k);
                        if k=1 then
                                begin
                                        inc(head[i]);
                                        inc(head[j]);
                                        inc(spt);
                                        canhx[spt]:=i;
                                        canhy[spt]:=j;
                                        inc(spt);
                                        canhx[spt]:=j;
                                        canhy[spt]:=i;
                                end;
                end;
        head[0]:=0;
        head[n+1]:=spt;
        for i:=1 to n do
                head[i]:=head[i-1]+head[i];
        for i:=1 to spt do
                begin
                        adj[head[canhx[i]]]:=canhy[i];
                        dec(head[canhx[i]]);
                end;
end;


procedure xuli;
var     i,j,x,y:data;
begin
        for i:=0 to n do
                dd[i]:=0;

        count:=0;
        for i:=1 to n do
                if dd[i]=0 then
                        begin
                                inc(count);
                                dfs(i);
                        end;
        for i:=1 to m do
                begin
                        readln(f,x,y);
                        if dd[x]<>dd[y] then
                                writeln('YES')
                        else
                                writeln('NO');
                end;
end;

begin
        assign(f,fi); reset(f);
        docfile;
        xuli;
        close(f);
end.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *