紀念一下,這是我第一次不依靠網上的**自己寫及格的一次題。雖然仍然執行超時,但是真的已經很給我這個**小白信心了
問題描述
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條道路中盡可能多的道路,但是還要保持牧場之間 的連通性。...