這個題關鍵在於怎麼處理這些點需要重複到達的問題 題目要求最後只剩乙個樹圖 即只留(n-1)條邊 我們把每條邊的邊權乘二 再加上左右兩節點的點權 作為新的邊權 然後套克魯斯卡爾 最後加上乙個最小的點權
1. 邊權乘二
那麼對於每一條邊edge[i] 它都連線了以左節點edge[i].u為根的子樹(左樹)和以右節點edge[i].v為根的子樹(右樹) 而題目要求最後必須回到出發點 那麼假設我們出發點在左樹 現在要經過edge[i]去遍歷右樹上的節點 去時走了一次edge[i] 因為要回到出發點 所以又走了一次edge[i] 所以這個一來一回是必不可少的 又因為我們返回時再次經過edge[i]時 肯定已經把右樹節點都處理完畢(不然你回來幹什麼。。) 所以每條邊必走兩次且只走兩次
2. 加上左右兩節點的點權
設節點p 其鄰接邊有 a b c d
如果我們走a來到了p(一次訪問) 現在要通過b c d去遍歷其下的子樹 因為要回到出發點 所以在回程時必經a各一次(b c d共三次)
所以每個節點有多少鄰接點 即度為多少 那它就要被經過幾次
可這些度是誰提供的呢 當然是邊啊 無向圖中每條邊會為左右兩個節點各貢獻乙個度 所以在這裡我們就可以把這些點權附加到邊權上了 這樣就可以處理了
3. 加上乙個最小的點權
出發時還要安慰出發點的那頭牛 等於經過了一次出發點 但我們是突然出現在出發點的 無法在出發點的度上體現出來 所以必須單獨考慮
不管我們把誰作為出發點 1 2條是不變的 所以哪個點權值小就把誰作為出發點
好囉嗦。。
#include using namespace std;
#define ll long long
#define n 0x3f3f3f3f3f3f3f3f
struct node
;node edge[100010];
ll val[10010];
int f[10010];
int n,m;
bool cmp(node n1,node n2)
int getf(int p)
}bool unite(int u,int v)
else return false;
}int main()
for(i=1;i<=m;i++)
for(i=1;i<=n;i++)
sort(edge+1,edge+m+1,cmp);
sum=0,cnt=0;
for(i=1;i<=m;i++)
if(cnt==n-1) break;
}minn=n;
for(i=1;i<=n;i++)
printf("%lld\n",sum+minn);
return 0;
}
藍橋安慰奶牛
如題 問題描述 farmer john變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連線n個牧場,牧場被連續地編號為1到n。每乙個牧場都是乙個奶牛的家。fj計畫除去p條道路中盡可能多的道路,但是還要保持牧場之間 的連通性。你首先要決定那些道路是需要保留的n 1條道路。第j條雙向道路連...
藍橋杯 安慰奶牛
演算法訓練 安慰奶牛 時間限制 1.0s 記憶體限制 256.0mb 錦囊1使用最小生成樹演算法。錦囊2將每條邊 a,b 的權值lj改變為2lj ca cb,然後使用最小生成樹來計算。問題描述 farmer john變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連線n個牧場,牧場被連...
藍橋杯安慰奶牛
紀念一下,這是我第一次不依靠網上的 自己寫及格的一次題。雖然仍然執行超時,但是真的已經很給我這個 小白信心了 問題描述 farmer john變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連線n個牧場,牧場被連續地編號為1到n。每乙個牧場都是乙個奶牛的家。fj計畫除去p條道路中盡可能...