安慰奶牛
- 描述
-
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
然後求出最小的那個用時最短的牧場過夜 加上去就可以了
下面看代碼:
-
- #include<stdio.h>
- #include<iostream>
- #include<string.h>
- #include<algorithm>
- using namespace std;
- #define max(a,b)((a > b)?(a):(b))
- #define MAX 0x7fffffff
- struct node
- {
- int u;
- int v;
- int cap;
- }edge[100100]; //每條路的屬性的
- int d[100100];
- int p[100100]; //記錄每個點的值的
- int f[100100]; //記錄每個點的父親節點的
- int M, n, m;
- bool cmp(node a,node b)
- {
- return a.cap < b.cap;
- }
- void add(int from,int to,int cap)
- {
- edge[M].u = from;
- edge[M].v = to;
- edge[M].cap = cap * 2 + p[from] + p[to]; //這個地方是去然後還得回來所以乘2
- M++;
- }
- int find(int x)
- {
- if(f[x] == x)return f[x];
- return f[x] = find(f[x]);
- }
- void kruskal()
- {
- int i;
- for(i = 1;i <= n;i++)
- {
- f[i] = i;
- d[i] = 0;
- }
- int u,v,fu,fv,sum = 0;
- for(i = 0;i < M;i++)
- {
- u = edge[i].u;
- v = edge[i].v;
- fu = find(u);
- fv = find(v);
- if(fu == fv)continue;//如果相同的話 那麼久直接加就可以了
- sum += edge[i].cap;
- f[fu] = fv; //這個地方別忘了 一定要把父親節點給寫了
- //d[u]++;
- //d[v]++;
- }
- int tmp = MAX;
- for(i = 1;i <= n;i++)
- {
- if(tmp > p[i])tmp = p[i];
- }
- printf("%d\n",sum + tmp);
- }
- int main()
- {
- int i;
- int s,t,c;
- while(~scanf("%d%d",&n,&m))
- {
- for(i = 1;i <= n;i++)
- {
- scanf("%d",&p[i]);
- }
- for(i = 0;i < m;i++)
- {
- scanf("%d%d%d",&s,&t,&c);
- add(s,t,c);
- }
- sort(edge,edge + M,cmp);
- kruskal();
- }
- return 0;
- }
-