日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

蓝桥杯 ALGO-6 安慰奶牛

發(fā)布時(shí)間:2023/12/8 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯 ALGO-6 安慰奶牛 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

問(wèn)題描述

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

輸入格式

第1行包含兩個(gè)整數(shù)N和P。

接下來(lái)N行,每行包含一個(gè)整數(shù)Ci。

接下來(lái)P行,每行包含三個(gè)整數(shù)Sj, Ej和Lj。

輸出格式

輸出一個(gè)整數(shù), 所需要的總時(shí)間(包含和在你所在的牧場(chǎng)的奶牛的兩次談話時(shí)間)。

樣例輸入

5 6
10
10
20
6
30
1 2 5
2 3 5
2 4 12
3 4 17
2 5 15
3 5 6

樣例輸出

176(數(shù)據(jù)有誤,應(yīng)該是178

數(shù)據(jù)規(guī)模與約定

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

題意:這道題其實(shí)本身不是特別難,主要就是題意難以理解,主要是計(jì)算安慰所有的牛最短的時(shí)間,所有的牧場(chǎng)中的牛要安慰一次,但是題意指出起始點(diǎn)的牛要安慰?jī)纱巍8鶕?jù)題意構(gòu)造一顆最小生成樹(shù)即解決總的安慰時(shí)間最短,但是樹(shù)中的節(jié)點(diǎn)也存在權(quán)值,所以不能按照常規(guī)的套路來(lái)做,看了網(wǎng)上的許多老鐵做的方法,把2*邊的權(quán)值+邊連接兩點(diǎn)的安慰時(shí)長(zhǎng)作為邊的新的權(quán)值,然后在使用最小生成樹(shù)的方法。藍(lán)橋杯的官網(wǎng)的錦囊也說(shuō)了這個(gè)方法。

思路:用結(jié)構(gòu)體保存兩點(diǎn)以及兩點(diǎn)之間新的權(quán)值,然后加入優(yōu)先級(jí)隊(duì)列中,對(duì)<進(jìn)行重載后,按照權(quán)值從小到大的順序排列,然后使用克魯斯卡爾算法解決總的時(shí)長(zhǎng)。此算法中使用了并查集來(lái)解決問(wèn)題,對(duì)于一顆最小生成樹(shù),只有集合,對(duì)優(yōu)先級(jí)隊(duì)列中的元素中包含的兩點(diǎn)依次判斷,判斷是否屬于一個(gè)集合中,不屬于一個(gè)集合要進(jìn)行合并,此處合并對(duì)于小樹(shù)貼到大樹(shù)上的優(yōu)點(diǎn)不明顯,和任意貼時(shí)間差不多,但是路徑壓縮還是需要的,樹(shù)一直長(zhǎng)高會(huì)導(dǎo)致查找效率變低,所以要進(jìn)行路徑壓縮。

我在最后就是發(fā)現(xiàn)在藍(lán)橋杯的OJ上不能使用system("pause");來(lái)使運(yùn)行框暫停,會(huì)報(bào)錯(cuò)一個(gè)測(cè)試點(diǎn)都通不過(guò)。所以一定不要手殘加了!!!

代碼1:小樹(shù)貼到大樹(shù)上

#include <iostream> #include<queue> #include<algorithm> #define N 10010 using namespace std; struct node {int u, v, dis;node(int u, int v, int d) :u(u), v(v), dis(d) {}friend bool operator < (const node &a, const node &b) {//重載小于運(yùn)算負(fù),使用優(yōu)先級(jí)隊(duì)列 return a.dis > b.dis;} }; priority_queue<node> q; int cost[N],s[N]; int find(int x) {//尋找父節(jié)點(diǎn),并且進(jìn)行路徑壓縮 if (s[x] < 0)return x;else {return s[x] = find(s[x]);} } void Union(int u, int v) {//合并兩個(gè)節(jié)點(diǎn) int rootU = find(u), rootV = find(v);if (rootU != rootV) {//操作的是對(duì)于根節(jié)點(diǎn)而而言的,if (s[rootU] < s[rootV]) {//值表示根節(jié)點(diǎn)的規(guī)模,將小的樹(shù)掛在大的樹(shù)上面 s[rootU] += s[rootV];s[rootV] = rootU;}else {s[rootV] += s[rootU];s[rootU] = rootV;}} } int kruskal() {//使用克魯斯卡爾算法計(jì)算最小生成樹(shù),對(duì)于一顆最小生成樹(shù)而言,其任意兩點(diǎn)的父節(jié)點(diǎn)是相等的 int sumDis = 0;while (!q.empty()) {node tem = q.top();q.pop();int root1 = find(tem.u), root2 = find(tem.v);if (root1 != root2) {sumDis += tem.dis;Union(root1,root2);//將兩個(gè)點(diǎn)的合并成一個(gè)集合 }}return sumDis; } int main(int argc, char** argv) {fill(s, s + N, -1);//初始化所有節(jié)點(diǎn)的父節(jié)點(diǎn) int n, p, a, b, c;cin >> n >> p;for (int i = 1; i <= n; i++) {//輸入所有節(jié)點(diǎn)的權(quán)值 scanf("%d", &cost[i]);}for (int i = 0; i < p; i++) {//輸入所有的節(jié)點(diǎn)以及所有的路徑 scanf("%d%d%d", &a, &b, &c);q.push(node{ a,b,(2 * c + cost[a] + cost[b]) }); //把路徑的兩倍+路徑上兩個(gè)節(jié)點(diǎn)的和作為邊的新權(quán)值 }int sumCost = kruskal();sumCost += *min_element(cost+1,cost+n);//min_element函數(shù)主要求出的是給定數(shù)組長(zhǎng)度的最小值cout << sumCost << endl;return 0; }

代碼2:第一個(gè)點(diǎn)貼在第二個(gè)點(diǎn)上

#include <iostream> #include<queue> #include<algorithm> #define N 10010 using namespace std; struct node {int u, v, dis;node(int u, int v, int d) :u(u), v(v), dis(d) {}friend bool operator < (const node &a, const node &b) {//重載小于運(yùn)算負(fù),使用優(yōu)先級(jí)隊(duì)列 return a.dis > b.dis;} }; priority_queue<node> q; int cost[N], mindis, s[N]; int find(int x) {//尋找父節(jié)點(diǎn),并且進(jìn)行路徑壓縮 if (s[x] < 0)return x;else {return s[x] = find(s[x]);} } int kruskal() {//使用克魯斯卡爾算法計(jì)算最小生成樹(shù),對(duì)于一顆最小生成樹(shù)而言,其任意兩點(diǎn)的父節(jié)點(diǎn)是相等的 int sumDis = 0;while (!q.empty()) {node tem = q.top();q.pop();int root1 = find(tem.u), root2 = find(tem.v);if (root1 != root2) {sumDis += tem.dis;s[root1] = root2;}}return sumDis; } int main(int argc, char** argv) {fill(s, s + N, -1);//初始化所有節(jié)點(diǎn)的父節(jié)點(diǎn) int n, p, a, b, c;cin >> n >> p;for (int i = 1; i <= n; i++) {//輸入所有節(jié)點(diǎn)的權(quán)值 scanf("%d", &cost[i]);}for (int i = 0; i < p; i++) {//輸入所有的節(jié)點(diǎn)以及所有的路徑 scanf("%d%d%d", &a, &b, &c);q.push(node{ a,b,(2 * c + cost[a] + cost[b]) }); //把路徑的兩倍+路徑上兩個(gè)節(jié)點(diǎn)的和作為邊的新權(quán)值 }int sumCost = kruskal();sumCost += *min_element(cost+1,cost+n);cout << sumCost << endl;return 0; }

?

總結(jié)

以上是生活随笔為你收集整理的蓝桥杯 ALGO-6 安慰奶牛的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。