安慰奶牛

安慰奶牛

時間限制:1000 ms  |  內存限制:65535 KB
難度:3
描述
  Farmer John最近變得非常懶,他不想再繼續維護供奶牛通行的道路。這些道路被用來連接N個牧場,牧場編號爲1到N。每一個牧場是一個奶牛的家。FJ計劃除去M條道路中儘可能多的道路,但是還要保持牧場之間的連通。因爲奶牛們的交通系統被破壞了,所以她們非常傷心,於是,FJ決定去安慰她們。現在已知每條道路的起點S和終點E(1 <= S <= N,1 <= E <= N,S != E),以及走完這條路需要的時間L。當FJ到達第i個牧場的時候(即使已經到過),他必須花去Ci的時間和奶牛交談。在早上出發和晚上回去的時候,他都需要和他所在牧場的奶牛交談一次。假設一天可以談完,談完後必須回到早上出發的點(出發點可以任意選擇),這樣纔算完成他的交談任務。
  FJ想知道安慰所有的奶牛至少需要多長的時間,聰明的你能告訴他嗎?
輸入
多組測試數據。
對於每組數據,第1行包含兩個整數N和M。
接下來N行,每行包含1個整數Ci(1<=Ci<=1000)。
接下來M行,每行包含三個整數S, E和L(1<=L<=1000)。
輸出
輸出一個整數, 表示所需要的總時間(包含和在你所在的牧場的奶牛的兩次談話時間)。
樣例輸入
5 7
10
10
20
6
30
1 2 5
2 3 5
2 4 12
3 4 17
2 5 15
3 5 6
4 5 12
樣例輸出
176

  

思路:這就是一道簡單的最小生成樹的問題可是我們要注意的是  當我們去了一個地方我們要走回來的所以我們要把兩個點的距離乘2

然後求出最小的那個用時最短的牧場過夜 加上去就可以了 

下面看代碼:

    1. #include<stdio.h>  
    2. #include<iostream>  
    3. #include<string.h>  
    4. #include<algorithm>  
    5.   
    6.   
    7. using namespace std;  
    8.   
    9. #define max(a,b)((a > b)?(a):(b))  
    10. #define MAX 0x7fffffff  
    11. struct node  
    12. {  
    13.     int u;  
    14.     int v;  
    15.     int cap;  
    16. }edge[100100];  //每條路的屬性的  
    17. int d[100100];  
    18. int p[100100];   //記錄每個點的值的  
    19. int f[100100];   //記錄每個點的父親節點的  
    20. int M, n, m;  
    21. bool cmp(node a,node b)  
    22. {  
    23.     return a.cap < b.cap;  
    24. }  
    25. void add(int from,int to,int cap)  
    26. {  
    27.     edge[M].u = from;  
    28.     edge[M].v = to;  
    29.     edge[M].cap = cap * 2 + p[from] + p[to]; //這個地方是去然後還得回來所以乘2  
    30.     M++;  
    31. }  
    32. int find(int x)  
    33. {  
    34.     if(f[x] == x)return f[x];  
    35.     return f[x] = find(f[x]);  
    36. }  
    37. void kruskal()  
    38. {  
    39.     int i;  
    40.     for(i = 1;i <= n;i++)  
    41.     {  
    42.         f[i] = i;  
    43.         d[i] = 0;  
    44.     }  
    45.     int u,v,fu,fv,sum = 0;  
    46.     for(i = 0;i < M;i++)  
    47.     {  
    48.         u = edge[i].u;  
    49.         v = edge[i].v;  
    50.         fu = find(u);  
    51.         fv = find(v);  
    52.         if(fu == fv)continue;//如果相同的話 那麼久直接加就可以了  
    53.         sum += edge[i].cap;  
    54.         f[fu] = fv;   //這個地方別忘了 一定要把父親節點給寫了  
    55.         //d[u]++;  
    56.         //d[v]++;  
    57.     }  
    58.     int tmp = MAX;  
    59.     for(i = 1;i <= n;i++)  
    60.     {  
    61.         if(tmp > p[i])tmp = p[i];  
    62.     }  
    63.     printf("%d\n",sum + tmp);  
    64. }  
    65. int main()  
    66.   
    67. {  
    68.     int i;  
    69.     int s,t,c;  
    70.     while(~scanf("%d%d",&n,&m))  
    71.     {  
    72.         for(i = 1;i <= n;i++)  
    73.         {  
    74.             scanf("%d",&p[i]);  
    75.         }  
    76.         for(i = 0;i < m;i++)  
    77.         {  
    78.             scanf("%d%d%d",&s,&t,&c);  
    79.             add(s,t,c);  
    80.         }  
    81.         sort(edge,edge + M,cmp);  
    82.         kruskal();  
    83.     }  
    84.     return 0;  
    85.   
    86. }    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章