1. 程式人生 > >算法訓練 安慰奶牛

算法訓練 安慰奶牛

需要 而且 內存 can enter 們的 端點 必須 道路

算法訓練 安慰奶牛 時間限制:1.0s 內存限制:256.0MB 問題描述

Farmer John變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連接N個牧場,牧場被連續地編號為1到N。每一個牧場都是一個奶牛的家。FJ計劃除去P條道路中盡可能多的道路,但是還要保持牧場之間 的連通性。你首先要決定那些道路是需要保留的N-1條道路。第j條雙向道路連接了牧場Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N; Sj != Ej),而且走完它需要Lj的時間。沒有兩個牧場是被一條以上的道路所連接。奶牛們非常傷心,因為她們的交通系統被削減了。你需要到每一個奶牛的住處去安慰她們。每次你到達第i個牧場的時候(即使你已經到過),你必須花去Ci的時間和奶牛交談。你每個晚上都會在同一個牧場(這是供你選擇的)過夜,直到奶牛們都從悲傷中緩過神來。在早上 起來和晚上回去睡覺的時候,你都需要和在你睡覺的牧場的奶牛交談一次。這樣你才能完成你的 交談任務。假設Farmer John采納了你的建議,請計算出使所有奶牛都被安慰的最少時間。

輸入格式

第1行包含兩個整數N和P。

接下來N行,每行包含一個整數Ci。

接下來P行,每行包含三個整數Sj, Ej和Lj。

輸出格式 輸出一個整數, 所需要的總時間(包含和在你所在的牧場的奶牛的兩次談話時間)。 樣例輸入 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 數據規模與約定

5 <= N <= 10000,N-1 <= P <= 100000,0 <= Lj <= 1000,1 <= Ci <= 1,000。

題目本身少了一組數據,以上補上了。

輸入一個無向圖,以及每個點安慰奶牛用時間,任務是尋找一個生成樹,使你從這個樹的某個節點開始按照某種順序遍歷 這棵樹花費的時間最少。花費時間定義為每條邊上的時間和到達某一個節點時(無論你之前是否已經去過)該節點的時間。

首先我們著眼於生成一棵樹。有點類似與最小生成樹但又不是純粹的最小生成樹。然後註意到題目的關鍵在於遍歷整棵樹一次。這意味著什麽?不就是每條邊都會被走兩次嗎??!!
然後就是每個點的權值。用草稿紙分析可以得出,樹中一個度數為d的節點在遍歷的過程中一定走了d次!!!當然,起點會多一次,即d+1次(我們就選最小權值的點當起點)。

  首先這個題是最小生成樹問題,但是沒有現成的生成樹,所以我們就先構造一個。對於每條邊,如果選的話,則要耗去來回一趟和訪問2個端點所用的的時間總合,所以將圖中各個邊的權值改為邊本來的權值的兩倍加上訪問兩端點的值,這樣一棵樹就構造好。至於住在哪間房裏面,選擇Ci最小的那一間就可以了。

代碼如下:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #include <queue>
 5 #define N 10050
 6 #define M 100005
 7 #define ll long long int
 8 using namespace std;
 9 int n,m;
10 struct Node{
11     int u,v,cost;
12 };
13 bool cmp(Node a,Node b){
14     return a.cost<b.cost;
15 }
16 int fa[N];
17 Node node[M];
18 int vis[N];
19 int find(int x){
20     return x==fa[x] ? x :  fa[x]=find(fa[x]);
21 }
22 
23 void init(){
24     for(int i=0;i<=N;i++)
25         fa[i] = i;
26 }
27 int kruskal(){
28     init();
29     int cnt = 0;
30     int t = 0;
31     for(int i=0;i<m;i++){
32         int x = find(node[i].u);
33         int y = find(node[i].v);
34         if(x!=y){
35             fa[x] = y;
36             cnt += node[i].cost;
37             t++;
38         }
39     }
40     return cnt;
41 }
42 int main(){
43     std::ios::sync_with_stdio(false);
44     std::cin.tie(0);
45     // scanf("%d%d",&n,&m);
46     cin>>n>>m;
47     int mi = 2005,c;
48     for(int i=1;i<=n;i++){
49         cin>>vis[i];
50         mi = min(mi,vis[i]);
51     }
52     for(int i=0;i<m;i++){
53         cin>>node[i].u>>node[i].v>>c;
54         node[i].cost = c*2 + vis[node[i].u] + vis[node[i].v];
55     }
56     sort(node,node+m,cmp);
57     int ans = kruskal() + mi;
58     cout<<ans<<endl;
59     // printf("%d\n", ans);
60     return 0;
61 }

算法訓練 安慰奶牛