http://acm.hdu.edu.cn/showproblem.php?pid=1879  继续畅通工程

寻找最小生成树,可以使用prim算法,亦可以使用kruskal算法。以下使用prim算法实现。

 
  
  1. //继续畅通工程   prim算法  
  2. #include<stdio.h>  
  3. #define N 105  
  4. int matrix[N][N];  
  5. int flag[N];  
  6. int length[N];  
  7. int d[N];  
  8.  
  9. int get_min(int n)  
  10. {  
  11.     int min;  
  12.     int i;  
  13.     for (i = 1; i <= n; i++)  
  14.     {  
  15.         if (flag[i] == 0)  
  16.         {  
  17.             min = i;  
  18.             break;  
  19.         }  
  20.     }  
  21.     for (i++; i <= n; i++)  
  22.     {  
  23.         if (flag[i] == 0 && length[min] > length[i])  
  24.             min = i;  
  25.     }  
  26.     return min;  
  27. }  
  28.  
  29. int prim(int n)  
  30. {  
  31.     int i, j;  
  32.     int min;  
  33.     int sum;  
  34.     for (i = 1; i <= n; i++)  
  35.     {  
  36.         flag[i] = 0;  
  37.         length[i] = matrix[1][i];  
  38.         d[i] = 1;  
  39.     }  
  40.     flag[1] = 1;  
  41.     sum = 0;  
  42.     for (i = 2; i <= n; i++)  
  43.     {  
  44.         min = get_min(n);  
  45.         flag[min] = 1;  
  46.         sum += length[min];  
  47.         for (j = 1; j <= n; j++)  
  48.         {  
  49.             if (flag[j] == 0)  
  50.             {  
  51.                 if (matrix[min][j] < length[j])  
  52.                 {  
  53.                     length[j] = matrix[min][j];  
  54.                     d[j] = min;  
  55.                 }  
  56.             }  
  57.         }  
  58.     }  
  59.     return sum;  
  60. }  
  61.  
  62. void main()  
  63. {  
  64.     int n, m;  
  65.     int i;  
  66.     int min;  
  67.     int u, v, cost, tag;  
  68.  
  69. //  freopen("input.txt", "r", stdin);  
  70.     while (scanf("%d", &n) != EOF && n != 0)  
  71.     {  
  72.         m = n * (n - 1) / 2;  
  73.         for (i = 0; i <= n; i++)  
  74.             matrix[i][i] = 0;  
  75.         for (i = 0; i < m; i++)  
  76.         {  
  77.             scanf("%d%d%d%d", &u, &v, &cost, &tag);  
  78.             if (tag == 1)  
  79.             {  
  80.                 matrix[u][v] = 0;  
  81.                 matrix[v][u] = 0;  
  82.             }  
  83.             else 
  84.             {  
  85.                 matrix[u][v] = cost;  
  86.                 matrix[v][u] = cost;  
  87.             }  
  88.         }  
  89.         min = prim(n);  
  90.         printf("%d\n", min);  
  91.     }  
  92. }  

 以下是Kruskal算法,先使用快速排序为两个城市的成本排序,再使用并查集判断增加某条边后是否构成环。

 
  
  1. //继续畅通工程   kruskal算法与使用并查集  
  2. #include<stdio.h>  
  3. #define N 105  
  4. struct arc_node{  
  5.     int u, v;  
  6.     int cost;  
  7. };  
  8. struct arc_node edge[N * (N - 1) / 2];  
  9. int parent[N];  
  10. int height[N];  
  11. int qsort(int low, int high)  
  12. {  
  13.     struct arc_node t;  
  14.     int temp;  
  15.     int i, j;  
  16.     if (low < high)  
  17.     {  
  18.         temp = edge[high].cost;  
  19.         i = low;  
  20.         for (j = low; j < high; j++)  
  21.         {  
  22.             if (edge[j].cost < temp)  
  23.             {  
  24.                 t = edge[j];  
  25.                 edge[j] = edge[i];  
  26.                 edge[i] = t;  
  27.                 i++;  
  28.             }  
  29.         }  
  30.         t = edge[j];  
  31.         edge[j] = edge[i];  
  32.         edge[i] = t;  
  33.         qsort(low, i - 1);  
  34.         qsort(i + 1, high);  
  35.     }  
  36.     return 1;  
  37. }  
  38.  
  39. int get_parent(int n)  
  40. {  
  41.     while (parent[n] != n)  
  42.         n = parent[n];  
  43.     return n;  
  44. }  
  45. void main()  
  46. {  
  47.     int n, m;  
  48.     int tag;  
  49.     int i;  
  50.     int sum, count;  
  51.     int temp1, temp2;  
  52.  
  53. //  freopen("input.txt", "r", stdin);  
  54.     while (scanf("%d", &n) != EOF && n != 0)  
  55.     {  
  56.         m = n * (n - 1) / 2;  
  57.         for (i = 0; i < m; i++)  
  58.         {  
  59.             scanf("%d%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost, &tag);  
  60.             if (tag == 1)  
  61.             {  
  62.                 edge[i].cost = 0;  
  63.             }  
  64.         }  
  65.         qsort(0, m - 1);  
  66.         for (i = 1; i <= n; i++)  
  67.         {  
  68.             parent[i] = i;  
  69.             height[i] = 1;  
  70.         }  
  71.         count = 0;  
  72.         sum = 0;  
  73.         for (i = 0; i < m; i++)  
  74.         {  
  75.             temp1 = get_parent(edge[i].u);  
  76.             temp2 = get_parent(edge[i].v);  
  77.             if (temp1 != temp2)  
  78.             {  
  79.                 count++;  
  80.                 sum += edge[i].cost;  
  81.                 if (height[temp1] == height[temp2])  
  82.                 {  
  83.                     height[temp1]++;  
  84.                     parent[temp2] = temp1;  
  85.                 }  
  86.                 else 
  87.                 {  
  88.                     if (height[temp1] > height[temp2])  
  89.                         parent[temp2] = temp1;  
  90.                     else 
  91.                         parent[temp1] = temp2;  
  92.                 }  
  93.                 if (count == n - 1)  
  94.                     break;  
  95.             }  
  96.         }  
  97.         printf("%d\n", sum);          
  98.     }