1. 程式人生 > 其它 >PTA 7-7 六度空間 思路分析及程式碼解析

PTA 7-7 六度空間 思路分析及程式碼解析

技術標籤:資料結構學習資料結構演算法圖論

PTA 7-7 六度空間 思路分析及程式碼解析 v0.96

一、前導

1. 需要掌握的知識

圖的儲存和遍歷

2. 題目資訊

題目來源:PTA / 拼題A
題目地址:https://pintia.cn/problem-sets/15/problems/715

二、解題思路分析

1. 題意理解

  1. 輸入資料
10 9	//10表示網路中的頂點數,9表示網路中存在的邊數
1 2  //如下9行表示圖中的邊
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
  1. 輸出資料:列印與該結點距離不超過6的結點數佔結點總數的百分比,精確到小數點後兩位
1: 70.00%
2: 80.00%
3: 90.00%
4: 100.00%
5: 100.00%
6: 100.00%
7: 100.00%
8: 90.00%
9: 80.00%
10: 70.00%
  1. 題意
    圖的廣度優先搜尋的應用

2. 思路分析(重點)

  1. 通過二維陣列儲存圖
  2. 典型的BFS遍歷,參考樹的層序遍歷實現即可
  3. 如果使用的是C++,輸出格式有點小麻煩

三、具體實現

1. 彎路和bug

  1. 不要忘記初始化,每個頂點統計完畢後都需要進行 /(ㄒoㄒ)/~~
  2. 統計結果的變數需要設定為double,初始值為1:因為自己也滿足統計要求

2. 程式碼框架(重點)

2.1 採用的資料結構

二維陣列儲存圖,提升了編碼效率;如果想進一步提升,需要再試試連結串列

int a[max][max];
int dist[max];  //通過dist[]陣列記錄層數
bool visited[max]; //通過visited[]陣列統計頂點是否被訪問

2.2 程式主體框架

               程式偽碼描述
int main()
{	
	1.建立圖
	2.迴圈,每個頂點執行BFS()並按要求列印輸出
}

2.3 各分支函式

  1. void bfs(int node); //廣度遍歷,核心函式
    1.1 通過dist[ ]陣列統計層數
    1.2 通過result變數統計符合要求的人數
    1.3 滿足要求後 或者 迴圈結束,執行列印函式
void bfs(int node)
{ dist[node]=0; visited[node]=true; q.push(node); while(!q.empty()) { front=q.front(); q.pop(); for(int i=1;i<N+1;i++) { if(a[front][i] && !visited[i]) { q.push(i); visited[i]=true; dist[i]=dist[front]+1; if(dist[i]>6) { Print(node,result); return; } result++; } } } Print(node,result); return; }
  1. void Print(int node,double result);
    對於C++,列印有點小麻煩,需要iomanip的幫助
 #include <iomanip>
void Print(int node,double result)
{
	result = result/N*100;
	cout.setf(ios::fixed);
	cout<<node<<": "<<fixed<<setprecision(2)<<result<<"%"<<endl;
}

  1. void creat(); //先建立一個空圖,然後填充好邊;由於是無向圖,邊需要儲存兩次
void creat()
{
	cin>>N>>M; //N represent Node, M represent Edge
	for(int i=0;i<max;i++)
		for(int j=0;j<max;j++)
			a[i][j]=0;
	int x,y;
	for(int k=0;k<M;k++)
	{
		cin>>x>>y;
		a[x][y]=1;
		a[y][x]=1;
	}
	return;
}
  1. void Default(); //初始化函式
void Default()
{
	result=1;  //滿足要求的人重置為1,因為自己也滿足要求
	for(int i=0;i<max;i++)
	{
		dist[i]==-1;  //dist[]陣列用來標記範圍
		visited[i]=false; //將所有結點重置為未訪問
	}
	while(!q.empty()) //清空佇列
		q.pop(); 
}

3. 完整編碼

#include <iomanip>
#include <queue>
#include <iostream>
using namespace std;

#define max 1001  //N<=1000 

int a[max][max];
int N,M;
queue<int> q;
double result=1;

int dist[max];
bool visited[max];
void bfs(int node);
void creat();
void Default();
void Print(int node,double result);

int main()
{
	Default();
	
	creat();
	
	for(int i=1;i<N+1;i++)
	{
		bfs(i);
		Default();
	}
	
	return 0;
}

void bfs(int node)
{
	int front;
	dist[node]=0;
	visited[node]=true;
	q.push(node);
	
	while(!q.empty())
	{
		front=q.front();
		q.pop();
		
		for(int i=1;i<N+1;i++)
		{
			if(a[front][i] && !visited[i])
			{
				q.push(i);
				visited[i]=true;
				dist[i]=dist[front]+1;
				if(dist[i]>6)
				{
					Print(node,result);
					return;
				}
				result++;
			}
		}
		
	}
	Print(node,result);
	return;
}

void Print(int node,double result)
{
	result = result/N*100;
	cout.setf(ios::fixed);
	cout<<node<<": "<<fixed<<setprecision(2)<<result<<"%"<<endl;
}

void Default()
{
	result=1;
	for(int i=0;i<max;i++)
	{
		dist[i]==-1;
		visited[i]=false;
	}
	while(!q.empty())
		q.pop();
}


void creat()
{
	cin>>N>>M;
	for(int i=0;i<max;i++)
	{
		dist[i]==-1;
		visited[i]=false;
		for(int j=0;j<max;j++)
		{
			a[i][j]=0;
		}
	}
	
	int x,y;
	for(int k=0;k<M;k++)
	{
		cin>>x>>y;
		a[x][y]=1;
		a[y][x]=1;
	}
	return;
}

四、參考資料

1. 浙江大學 陳越、何欽銘老師主講的資料結構