藍橋杯安慰奶牛

2021-08-17 19:01:25 字數 4902 閱讀 5936

紀念一下,這是我第一次不依靠網上的**自己寫及格的一次題。雖然仍然執行超時,但是真的已經很給我這個**小白信心了

問題描述

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

樣例輸出

176資料規模與約定

5 <= n <= 10000,n-1 <= p <= 100000,0 <= lj

<= 1000,1 <= ci

<= 1,000。

首先,資料給的是錯的,要是有人看的話,建議不要按他給的資料用

然後,這裡主要考察了最小生成樹的思想。

下面是我一開始的思路

#include

int a[100005];//巨集定義,要是在int main裡沒辦法開 

int b[100005];

int c[100005];

int l[10005];

struct node//定義乙個節點,包含他的指向和指向點所對應的距離和乙個flag變數 

;node node[10005];

int main()

int temp,temp1;

int k=0;

//for (i=1;i<=p;i++)

////實際上這裡是乙個氣泡排序。因此會執行超時。我覺得可以改善成快排,但是我不想去改了 

int min;

for (i=1;i<=n-1;i++)

}//這段**理解較為困難。

//我們應該注意到,每個雙向的邊它可以用單向邊去表示。

//如果沒有下面這一段**,若是有乙個點需要連著兩條或者更多條線路

//那麼後面的就會覆蓋前面的

//本來應該使用之前學的dnf那一塊思想去遍歷

//後來覺得太煩,就發現總共只有n-1條邊,那麼乙個點應該只有不到1條定義邊

//那麼我就可以對即將被覆蓋掉的資料,先送給他所指向的那個點

//這樣雖然會反掉順序,但是不會丟失資料 

if (node[a[temp]].zhi!=0&&node[node[temp].zhi].zhi==0)

//賦值語句,很好理解 

node[a[temp]].zhi=b[temp];

node[a[temp]].ju=min;

//flag全為0,直接賦值就可以了。為了不讓k重複,就要讓他不斷增加 

if (node[a[temp]].flag==node[b[temp]].flag&&node[b[temp]].flag==0)

//乙個為0,將另乙個為0的替換 

if (node[a[temp]].flag!=node[b[temp]].flag&&(node[a[temp]].flag==0||(node[b[temp]].flag==0)))

//這裡就是和上面的全部"歸為乙個點 "呼應了。改掉乙個點並不夠

//還要將和他一樣的點全部改掉 

//找大的其實沒有必要就是為了好看 

if (node[a[temp]].flag!=node[b[temp]].flag&&node[b[temp]].flag!=0&&(node[a[temp]].flag!=0))

}if (node[a[temp]].flag    }}

temp=99999;//temp重新置無窮 

}for (i=1;i<=n;i++)

}return 0;

我一開始寫的時候遇到乙個難題。就是後面出現的資料會覆蓋掉我之前記載的資料。

這個問題的最好的解法可能和之前的那些dfs之類差不多

但是我在想,既然只有n-1條路,而我有n個點可以去儲存資料,那我調換一下位置不就沒有任何問題了嗎

於是出現了上面那一段**。

實際上那還是錯誤的

因為那個**只能調換一次,調換之後如果再遇到仍然會覆蓋。這樣去寫乙個迭代直到找到flag==0的時候應該也能解決問題。

但是那太煩了

我覺得還不如新開幾個陣列來儲存

但是那樣又太耗費空間了

那這樣不如找到乙個立刻輸出就是了

於是有了這一段**

#include

int a[100005];//巨集定義,要是在int main裡沒辦法開 

int b[100005];

int c[100005];

int l[10005];

int a1[100005];

int b1[100005];

int c1[100005];

struct node//定義乙個節點,包含他的指向和指向點所對應的距離和乙個flag變數 

;node node[10005];

int main()

int temp,temp1;

int k=0;

for (i=1;i<=p;i++)

int min;

for (i=1;i<=n-1;i++)

}printf("%d %d %d\n",a[temp],b[temp],c[temp]);

//flag全為0,直接賦值就可以了。為了不讓k重複,就要讓他不斷增加 

if (node[a[temp]].flag==node[b[temp]].flag&&node[b[temp]].flag==0)

//乙個為0,將另乙個為0的替換 

if (node[a[temp]].flag!=node[b[temp]].flag&&(node[a[temp]].flag==0||(node[b[temp]].flag==0)))

//這裡就是和上面的全部"歸為乙個點 "呼應了。改掉乙個點並不夠

//還要將和他一樣的點全部改掉 

//找大的其實沒有必要就是為了好看 

if (node[a[temp]].flag!=node[b[temp]].flag&&node[b[temp]].flag!=0&&(node[a[temp]].flag!=0))

}if (node[a[temp]].flag    }}

temp=99999;//temp重新置無窮 

}return 0;

好了這樣我們就有了乙個傻瓜式的最小生成樹

這樣代入到題目裡面去

#include

int a[100005];//巨集定義,要是在int main裡沒辦法開 

int b[100005];

int c[100005];

int c2[100005];

int l[10005];

int g[100005];//奶牛談話時間 

struct node//定義乙個節點,包含他的指向和指向點所對應的距離和乙個flag變數 

;node node[10005];

int main()

int temp,temp1;

int k=0;

for (i=1;i<=n;i++)

for (i=1;i<=p;i++)

for (i=1;i<=p;i++)

int min;

int sum=0;

int t=99999;

for (i=1;i<=n;i++)

for (i=1;i<=n-1;i++)

}    sum+=c[temp];

//flag全為0,直接賦值就可以了。為了不讓k重複,就要讓他不斷增加 

if (node[a[temp]].flag==node[b[temp]].flag&&node[b[temp]].flag==0)

//乙個為0,將另乙個為0的替換 

if (node[a[temp]].flag!=node[b[temp]].flag&&(node[a[temp]].flag==0||(node[b[temp]].flag==0)))

//這裡就是和上面的全部"歸為乙個點 "呼應了。改掉乙個點並不夠

//還要將和他一樣的點全部改掉 

//找大的其實沒有必要就是為了好看 

if (node[a[temp]].flag!=node[b[temp]].flag&&node[b[temp]].flag!=0&&(node[a[temp]].flag!=0))

}if (node[a[temp]].flag    }}

temp=99999;//temp重新置無窮 

}printf("%d",sum+t);

return 0;

我覺得還是學學網上的官方演算法比較好。

但是我畢竟要比賽了,一堆演算法我也記不住

還不如自己寫個能拿60分的

大家不必要關心我的**,但是這個學習方法還是值得留意的哈

藍橋杯 安慰奶牛

演算法訓練 安慰奶牛 時間限制 1.0s 記憶體限制 256.0mb 錦囊1使用最小生成樹演算法。錦囊2將每條邊 a,b 的權值lj改變為2lj ca cb,然後使用最小生成樹來計算。問題描述 farmer john變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連線n個牧場,牧場被連...

(水)安慰奶牛 藍橋杯

分析 最小生成樹的乙個變形。首先,最終必定是一顆樹,先隨便畫一顆樹然後自己模擬走一遍,會發現應該把連線某條邊的2個頂點的權值加入到邊權中,且邊權應該乘2,所以最終以2l point1 point2為邊權生成最小生成樹即可,至於起點在哪都不影響,只是因為睡前還要安慰一遍睡覺的頂點的奶牛 即起點的奶牛 ...

藍橋杯 演算法訓練 安慰奶牛

演算法訓練 安慰奶牛 時間限制 1.0s 記憶體限制 256.0m 問題描述 farmer john變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連線n個牧場,牧場被連續地編號為1到n。每乙個牧場都是乙個奶牛的家。fj計畫除去p條道路中盡可能多的道路,但是還要保持牧場之間 的連通性。...