1. 程式人生 > >5-10 公路村村通 (30分)

5-10 公路村村通 (30分)

包括 lose com 保留 ant 天下 統計數據 -1 value

5-10 公路村村通 (30分)

現有村落間道路的統計數據表中,列出了有可能建設成標準公路的若幹條道路的成本,求使每個村落都有公路連通所需要的最低成本。

輸入格式:

輸入數據包括城鎮數目正整數NN(\le 10001000)和候選道路數目MM(\le 3N3N);隨後的MM行對應MM條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。為簡單起見,城鎮從1到NN編號。

輸出格式:

輸出村村通需要的最低成本。如果輸入數據不足以保證暢通,則輸出-1?1,表示需要建設更多公路。

輸入樣例:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

輸出樣例:

12

----------分析-----------------------------
這是一個典型的最小生成樹的問題。當時去廈大夏令營面試的時候遇到這個問題,我束手無策。今天下午花了一個下午+晚上的時候才算搞清楚了些Prime算法。
算法的思路可自行百度。這裏貼出我寫的代碼
  1 #include <stdio.h>
  2 #define MAX_VEX_NUM 101
  3 #define MAX_VALUE 9999
  4 
  5 typedef struct Graph
  6 {
  7     int vex[MAX_VEX_NUM][MAX_VEX_NUM];
8 int vexNum; 9 int arsNum; 10 }Graph; 11 12 13 struct closedeg 14 { 15 int vex; 16 int lowcost; 17 } closedeg[MAX_VEX_NUM]; 18 19 void init(Graph *G) 20 { 21 int i, j; 22 for(i = 1; i <= G->vexNum; i++) 23 for(j = 1; j <= G->vexNum; j++)
24 G->vex[i][j] = MAX_VALUE; 25 } 26 27 int isLianTong(Graph *G) 28 { 29 int i, j, flag = 0; 30 for(i = 1; i <= G->vexNum; i++) 31 { 32 for(j = 1; j <= G->vexNum; j++) 33 { 34 if(G->vex[i][j] != MAX_VALUE) 35 { 36 flag ++; 37 break; 38 } 39 } 40 } 41 if(flag < G->vexNum) 42 return 0; 43 else 44 return 1; 45 } 46 47 void print(Graph *G) 48 { 49 int i, j; 50 for(i = 1; i <= G->vexNum; i++) 51 { 52 for(j = 1; j <= G->vexNum; j++) 53 printf("%d ", G->vex[i][j]); 54 printf("\n"); 55 } 56 } 57 58 int Min(Graph *G, struct closedeg cld[]) 59 { 60 int i, min = MAX_VALUE, min_index = 2; 61 for(i = 2; i <= G->vexNum; i++) 62 { 63 if(cld[i].lowcost != 0) 64 { 65 if(min > cld[i].lowcost) 66 { 67 min = cld[i].lowcost; 68 min_index = i; 69 } 70 } 71 } 72 return min_index; 73 } 74 75 void Prim(Graph *G, int v) 76 { 77 int i, e; 78 int k0, u0, v0; 79 int sum = 0; 80 closedeg[v].lowcost = 0; 81 for(i = 1; i <= G->vexNum; i++) //對V-U中的點進行初始化closedeg[] 82 { 83 if(i != v) 84 { 85 closedeg[i].vex = v; 86 closedeg[i].lowcost = G->vex[v][i]; 87 } 88 } 89 90 for(e = 1; e <= G->vexNum - 1; e++) //找到n-1條邊 91 { 92 93 k0 = Min(G, closedeg); 94 u0 = closedeg[k0].vex; //最小邊的點左端點 95 v0 = k0; //最小邊的點右端點 96 // printf("(%d, %d) \n", u0, v0);; //輸出最小邊 97 sum += G->vex[u0][v0]; 98 closedeg[k0].lowcost = 0; 99 for(i = 2; i <= G->vexNum; i++) 100 { 101 if(G->vex[k0][i] < closedeg[i].lowcost) 102 { 103 closedeg[i].lowcost = G->vex[k0][i]; 104 closedeg[i].vex = v0; 105 } 106 } 107 } 108 if(1 == isLianTong(G)) 109 printf("%d\n", sum); 110 else 111 printf("-1\n"); 112 } 113 114 void creat(Graph *G) 115 { 116 int i; 117 // FILE *fp; 118 // fp = fopen("input.txt", "r"); 119 scanf("%d %d", &G->vexNum, &G->arsNum); 120 // fscanf(fp, "%d %d", &G->vexNum, &G->arsNum); 121 init(G); 122 for(i = 1; i <= G->arsNum; i++) 123 { 124 int ars1, ars2, weight; 125 scanf("%d %d %d", &ars1, &ars2, &weight); 126 // fscanf(fp, "%d %d %d", &ars1, &ars2, &weight); 127 G->vex[ars1][ars2] = weight; 128 G->vex[ars2][ars1] = weight; 129 } 130 // print(G); 131 } 132 133 int main() 134 { 135 Graph G; 136 creat(&G); 137 Prim(&G, 1); 138 return 0; 139 }

這裏面有很多函數是這個題目所不需要的。因為我在寫這個程序的時候並不是一帆風順的,中間遇到過很多問題。所以保留了一些我改動的痕跡。

只可惜最後上傳的時候只能拿22分,剩下還有兩個測試點,我也不知道哪個地方出了問題。

技術分享

5-10 公路村村通 (30分)