DS博客作業06--圖


求投食~(點圖即可) # 1.本周學習總結 ## 1.1思維導圖 ![](https://img2018.cnblogs.com/blog/1475360/201906/1475360-20190602205621946-1747640727.png)

1.2談談你對圖結構的認識及學習體會

圖中的頂點關系比樹的更加復雜,不再是單純的層次關系,而是平等的,點與點都可能連通,所以存儲就需要模擬一個平面,在圖的關系比較稀疏是用鄰接表(使用線性存儲),反之使用鄰接矩陣,二維數據即可表示出一個平面。圖的問題,主要是遍歷和路徑,難點在於找到相應算法(或者多種算法結合),解決一些實際問題時一般都會對算法進行相應的改動。

2.PTA實驗作業

2.1.題目1:7-7 旅游規划

有了一張自駕旅游路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。現在需要你寫一個程序,幫助前來咨詢的游客找一條出發地和目的地之間的最短路徑。如果有若干條路徑都是最短的,那么需要輸出最便宜的一條路徑。
輸入格式:
輸入說明:輸入數據的第1行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號為0~(N−1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨后的M行中,每行給出一條高速公路的信息,分別是:城市1、城市2、高速公路長度、收費額,中間用空格分開,數字均為整數且不超過500。輸入保證解的存在。
輸出格式:
在一行里輸出路徑的長度和收費總額,數字間以空格分隔,輸出結尾不能有多余空格。
輸入樣例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
輸出樣例:
3 40

2.1.1設計思路

此題就是找最短路徑,可以使用Dijkstra,使用一個包括距離和價錢的結構體建圖,然后比較時優先考慮距離其次到價格。

結構體:

typedef struct
{
	int weight=INF;//距離
	int cost=INF;//價格
}VNode;

偽代碼:

int main()
{
	cin >> N >> M >> S >> D;
	輸入城市數量,和高速路和出發點、目的地 
	for (i = 0  to M) 
	{
		cin >> x >> y >> w >> c;
		讀入高速路信息
		graph[x][y].weight = graph[y][x].weight = w;//距離 
		graph[x][y].cost = graph[y][x].cost = c;//價格 
	}
	調用Dijkstra(S, D);
	return 0;
}

Dijkstra(S, D);函數

void Dijkstra(int v,int d)
{
	VNode dist[501];//記錄最短路徑 
	int k;
	int s[501] = { 0 };//S[i]=1表示頂點i在S中,S[i]=0表示頂點i在u中 
	VNode mindis; 
	for (i = 0 to N)//N個頂點 
	{
		dist[i].weight = graph[v][i].weight;//距離初始化 
		dist[i].cost = graph[v][i].cost;//價格初始化 
	}
	s[v] = 1;
	for (i = 0 to N - 1)
	{
		mindis.weight = INF  初始化為最大值 
		for (j = 0 toj < N)
		{
			if (s[j] == 0 && dist[j].weight <= mindis.weight)如果j屬於u中(沒有被選)並且距離小於等於最小值 
			{
				if (dist[j].weight < mindis.weight)距離小於最小值
				{
					k = j;
					mindis.weight = dist[j].weight;
					mindis.cost = dist[j].cost;
					把該頂點信息記錄 
				}
				else if(dist[j].cost < mindis.cost)距離相等,比較價格 
				{
					k = j;
					mindis.cost = dist[j].cost;
					把該頂點信息記錄
				}
			}
		}
		s[k] = 1;
		for (j = 0 to N)
		{
			if(j點屬於u(沒有被選過))
				if(如果k和j連通)
					if (graph[k][j].weight + dist[k].weight < dist[j].weight)如果過k點到j點的新路徑比原來短 
					{
						dist[j].weight = graph[k][j].weight + dist[k].weight;更新為短路徑 
						dist[j].cost = graph[k][j].cost + dist[k].cost;
					}
					else if(graph[k][j].weight + dist[k].weight == dist[j].weight)
					{
						if (graph[k][j].cost + dist[k].cost < dist[j].cost)如果過k點到j點的新路徑比原來便宜 
						{
							dist[j].cost = graph[k][j].cost + dist[k].cost;更新為新價格 
						}
					}
		}
	}
	輸出最短路徑和價格 
}

2.1.2代碼截圖



2.2.3本題PTA提交列表說明


Q:

看錯題目然后誤以為是輸出目的地和價格,然后以為是bug找半天.。。。(還能過一個是最騷的),仔細看題目發現是輸出路徑的長度和價格

2.2.題目2:7-6 修建道路

N個村庄,從1到N編號,現在請您興建一些路使得任何兩個村庄彼此連通。我們稱村庄A和B是連通的,當且僅當在A和B之間存在一條路,或者存在一個存在C,使得A和C之間有一條路,並且C和B是連通的。
已知在一些村庄之間已經有了一些路,您的工作是再興建一些路,使得所有的村庄都是連通的,並且興建的路的長度是最小的。
輸入格式:
第一行是一個整數N(3<=N<=100),代表村庄的數目。后面的N行,第i行包含N個整數,這N個整數中的第j個整數是第i個村庄和第j個村庄之間的距離,距離值在[1,1000]之間。
然后是一個整數Q(0<=Q<=N*(N+1)/2)。后面給出Q行,每行包含兩個整數a和b(1<=a<b<=N),表示在村庄a和b之間已經興建了路。
輸出格式:
輸出一行僅有一個整數,表示為使所有的村庄連通需要新建公路的長度的最小值。
輸入樣例:
3
0 990 692
990 0 179
692 179 0
1
1 2
輸出樣例:
179

2.2.1設計思路

此題要求是修建公路使得任何兩個村庄都有路到達並且是最短,對於題中提到村庄之間已經有公路,只需把此類村庄的距離當做0即可。然后通過prim生成最小生成樹
注意:為了簡單起見此題鄰接矩陣的0並非常規prim算法中代表已經加入U(標記為選過),而是代表距離為0,標記則由visite[i]完成。
int main()
{ 
	for (i=1 to N) 
	{
		for (j = 1 to N) 
		{
			讀入村庄之間的距離到矩陣中 
		}
	}
	for (i = 0  to  q)
	{
		讀入已經修有路的村庄 
		graph[a][b] = graph[b][a]=0設置距離為零 
	}
   調用prim函數 
	輸出最小修路長度 
	return 0;
}

prim函數

int Prim(int v)
{
	for (i = 1 to N)N個村庄 
	{
		對lowcost和closest數組初始化 
		lowcost[i] = graph[v][i]距離 
		closest[i] = v路徑 
	}
	visite[v] = 1標記已經加入U 
	for (i = 1 to N)
	{
		for (j = 1 to N)
		{
			查找lowcost中未加入U(即visite[j]=0)最小的點 
			用k記錄 
		}
		找到后把距離累加到sum中 
		把該點標記已經加入U 
		for (int j = 1; j <= N; j++)
		{
			修改lowcost和closet
			if (visite[j]== 0 && graph[k][j] < lowcost[j])如果通過k到未選的點有短的距離 
			{
				lowcost[j] = graph[k][j];
				closest[j] = k;
			}
		}
	}
	返回return sum;
}

2.2.2代碼截圖



2.2.3本題PTA提交列表說明


A:兩個wa,是此處之前沒有兩個置為0(無向圖),

2.3.題目3:7-3 六度空間

六度空間”理論又稱作“六度分隔(Six Degrees of Separation)”理論。這個理論可以通俗地闡述為:“你和任何一個陌生人之間所間隔的人不會超過六個,也就是說,最多通過五個人你就能夠認識任何一個陌生人。”如圖1所示。

假如給你一個社交網絡圖,請你對每個節點計算符合“六度空間”理論的結點占結點總數的百分比。
輸入格式:
輸入第1行給出兩個正整數,分別表示社交網絡圖的結點數N(1<N≤10
​4
​​,表示人數)、邊數M(≤33×N,表示社交關系數)。隨后的M行對應M條邊,每行給出一對正整數,分別是該條邊直接連通的兩個結點的編號(節點從1到N編號)。
輸出格式:
對每個結點輸出與該結點距離不超過6的結點數占結點總數的百分比,精確到小數點后2位。每個結節點輸出一行,格式為“結點編號:(空格)百分比%”。
輸入樣例:
10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
輸出樣例:
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%

2.3.1設計思路

此題有點的像樹的層次遍歷,使用queue輔助搜索,visite[i]標記已經認識過的人,然后通過廣度優先搜索,把所有人都認識完或者已經達到第六層(最多通過五個人認識)就可以結束搜索。
圖結構體
typedef struct
{
	int **edgs;(直接聲明數組會爆)
	double n, e;
}MatGraph;
int main()
{


    為鄰接矩陣分配內存,直接聲明會爆 
	for (i =  0 to  M)鄰接矩陣初始化 
	{
		int x, y;
		cin >> x >> y;
		G.edgs[x][y] = G.edgs[y][x] = 1;
	}
	for (i =  1  to  N)調用N次廣搜 
	{
		調用BFS(G, i);
	}
    delete內存 
	return 0;
}
void BFS(MatGraph G,int v)
{
	使用cur表示當前訪問的頂點 ,last表示該層次的最后一個頂點
	當cur==last聲明該層次遍歷結束 
	while (!q.empty()&&level<6)//隊空或者層數到6 
	{
		從隊列去隊頭元素 temp =cur= q.front();
		for (int i = 1; i <=G.n; i++)
		{
			if (G.edgs[temp][i] != 0 && visite[i] == 0)尋找通過當前點可以認識其他點 
			{
				visite[i] = 1;標記已認識 
				q.push(i);入隊 
				sum++;認識人數 
			}
		}
		if (cur == last)//遍歷一層結束 
		{
			if (!q.empty())
			{
				last = q.back();
				level++;
			}
		}
	}
	printf("%d: %.2f%%\n",v,sum*100 / (G.n));輸出結果 
}

2.3.2代碼截圖

2.3.3本題PTA提交列表說明


A:直接過了,注意下層次和標記就可以了,

3、上機考試錯題及處理辦法(-2--2分)

3.1.截圖錯題代碼

3.1.1題目:六度空間

3.2 錯的原因及處理方法

visite[i]等於1才是標記為已選,但是打錯,然后編譯器一直提示的是內存爆了,我以為是數組問題,后來才發現是該處錯誤引發的無限循環。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM