圖中的頂點關係比樹的更加複雜,再也不是單純的層次關係,而是平等的,點與點均可能連通,因此存儲就須要模擬一個平面,在圖的關係比較稀疏是用鄰接表(使用線性存儲),反之使用鄰接矩陣,二維數據便可表示出一個平面。圖的問題,主要是遍歷和路徑,難點在於找到相應算法(或者多種算法結合),解決一些實際問題時通常都會對算法進行相應的改動。
有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。如今須要你寫一個程序,幫助前來諮詢的遊客找一條出發地和目的地之間的最短路徑。若是有若干條路徑都是最短的,那麼須要輸出最便宜的一條路徑。
輸入格式:
輸入說明:輸入數據的第1行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號爲0~(N−1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨後的M行中,每行給出一條高速公路的信息,分別是:城市一、城市二、高速公路長度、收費額,中間用空格分開,數字均爲整數且不超過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算法
此題就是找最短路徑,能夠使用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);函數app
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;更新爲新價格 } } } } 輸出最短路徑和價格 }
Q:
看錯題目而後誤覺得是輸出目的地和價格,而後覺得是bug找半天.。。。(還能過一個是最騷的),仔細看題目發現是輸出路徑的長度和價格函數
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學習
此題要求是修建公路使得任何兩個村莊都有路到達而且是最短,對於題中提到村莊之間已經有公路,只需把此類村莊的距離當作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函數spa
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; }
A:兩個wa,是此處以前沒有兩個置爲0(無向圖),設計
六度空間」理論又稱做「六度分隔(Six Degrees of Separation)」理論。這個理論能夠通俗地闡述爲:「你和任何一個陌生人之間所間隔的人不會超過六個,也就是說,最多經過五我的你就可以認識任何一個陌生人。」如圖1所示。3d
假如給你一個社交網絡圖,請你對每一個節點計算符合「六度空間」理論的結點佔結點總數的百分比。
輸入格式:
輸入第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%code
此題有點的像樹的層次遍歷,使用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));輸出結果 }
A:直接過了,注意下層次和標記就能夠了,
visite[i]等於1纔是標記爲已選,可是打錯,而後編譯器一直提示的是內存爆了,我覺得是數組問題,後來才發現是該處錯誤引起的無限循環。