SPOJ.COM - Thuật toán bài PT07Y - Is it a tree

23/09/2016 5 minutes read
Share:

Đề bài:

Bạn được cho một đồ thị không trọng số, và vô hướng. Viết chương trình để kiểm tra xem nó có phải là cây hay không.

Đầu vào:

Dòng đầu tiên của đầu vào sẽ bao gồm 2 số nguyên N và M, tương ứng là số lượng các điểm và số lượng cạnh trên đồ thị, với 0 < N <= 10000, 0 <= M <= 20000. Tiếp theo là M dòng chứa thông tin M cạnh của đồ thị. Mỗi dòng bao gồm một cặp u,v, nghĩa là có 1 cạnh giữa 2 điểm u, v với 1 <= u,v <= N.

Đầu ra:

In ra "YES" nếu như đồ thị đó là cây, ngược lại in ra "NO".

Ví dụ:

Đầu vào:

3 2

1 2

2 3

Đầu ra:

YES

Các bạn có thể tham khảo đề bài tiếng anh và submit code tại: http://www.spoj.com/problems/PT07Y/

Phân tích:

  • Trước tiên, để giải được bài toán này, bạn phải hiểu thế nào là cây. Theo tôi hiểu một cách đơn giản là: cây là một đồ thị liên thông, và không có chu trình nào. Do đó, nếu cây có N đỉnh thì sẽ có đúng N-1 cạnh. + Ta sẽ dùng thuật toán tìm kiếm theo chiều sâu DFS để duyệt đồ thị.

Lời giải:

(Các bạn nên tự mình nghĩ ra thuật toán của bài toán trước khi tham khảo code của tôi nhé. Hãy phát huy tối đa khả năng sáng tạo của bản thân. Hơn nữa code tôi viết ra cũng chưa thật sự tối ưu. Nên rất mong nhận được sự chia sẻ của các bạn.)

Code C/C++:

#include<iostream>
using namespace std;
const int MAX = 10005;
int Matrix[MAX][MAX]; // Ma trận lưu trạng thái của đồ thị
bool Visit[MAX]; // Mảng đánh dấu mỗi điểm được thăm hay chưa
int cnt; // Đếm số điểm đi qua trong 1 lần duyệt để biết
// đồ thị có liên thông hay không
int N, M; // Lần lượt là số đỉnh và số cạnh
void Try(int u)
{
Visit[u] = 1;
cnt++;
for (int i = 1; i <= Matrix[u][0]; i++)
{
int v = Matrix[u][i];
if(!Visit[v]) Try(v);
}
}
int main()
{
ios::sync_with_stdio(false);
// Comment dòng này trước khi submit
freopen("input.txt","r",stdin);
cin >> N >> M;
if(M == 0) cout << "NO" << endl;
else
{
cnt = 0;
for(int i = 0; i <= N; i++)
{
Visit[i] = false;
for(int j = 0; j <= N; j++)
Matrix[i][j] = 0;
}
// Tại hàng thứ i trong ma trận,
// ta sẽ lưu id của những đỉnh kề với đỉnh i
// Matrix[i][0] lưu số lượng đỉnh kề.
for(int i = 0; i < M; i++)
{
int a, b, m;
cin >> a >> b;
m = ++Matrix[a][0];
Matrix[a][m] = b;
m = ++Matrix[b][0];
Matrix[b][m] = a;
}
// Nếu số cạnh < số đỉnh trừ 1 thì chắc chắn không phải là cây
if(M == N-1)
{
// Thử duyệt tại một điểm bất kì, ở đây là điểm 1
Try(1);
// Khi số cạnh là N - 1 và đi được qua hết N điểm
// thì chứng tỏ đồ thị liên thông.
// và không có chu trình. Nên sẽ là cây.
if(cnt == N) cout << "YES" << endl;
else cout << "NO" << endl;
}
else cout << "NO" << endl;
}
return 0;
}
view raw PT07Y.cpp hosted with ❤ by GitHub

Code by Phạm Văn Lâm

Share: