這道題目咋一看就是最小生成樹啊。
題目描述大概是這樣:
kcm要準備一顆聖誕樹,這棵樹有一些節點和邊組成。節點從1到n,根總是1.每個節點都有自己的總量,而邊的**是由邊的單價乘以子孫節點的重量。
求出這麼一顆有n個節點的樹,使花費最小。
很像最小生成樹,仔細研究,沒法這樣做。因為每條邊在找到這顆樹之前很難計算它的價值。
因為本來你算好的邊的價值,但是在去掉某些邊時,會導致邊的價值發生變化,那怎麼辦。。。。
這道題目開始我也是不知道怎麼計算,看到discuss說是最短路。試想最後已經得到乙個樹,而每條邊的價值就是子孫節點重量和乘以單價,可以轉換為,此節點重量乘以從根到本節點的最短路,這麼一轉化,問題瞬間變得簡單了。
那麼所有點的最短路徑一定是一棵樹嗎? 這個是顯然的 ,因為如果形成環了,到達某個點就出現了多個路徑,就要刪去長的那條,使其沒有環
樣例中的計算方法
4*40+3*50+2*60+3*(20+40+50+60)+2*30+1*(10+20+30+40+50+60)
=10*1+20*(1+3)+30*(2+1)+40*(4+1+3)+50*(3+1+3)+60*(1+2+3)
=10+80+90+320+350+360
=1210
題目要注意幾個地方
1、n=0或者1, 答案是0,而不是no answer
2、資料範圍大,要用long long
3、n=0或者1的時候也要將資料讀入,不能直接輸出0就不管輸入了,否則會re
4、注意是無向圖,建鄰接表的時候要雙向
5、資料量大,鄰接矩陣不行,必須鄰接表
搞清楚了這些,剩下就是簡單的spfa了
**:
#include#define maxn 50005
#define inf 10000000000000
struct edge
edge[2 * maxn];//鄰接表
int preedge[2 * maxn];//preedge[u],上一條以u為起點的邊在edge中的位置
long long dis[maxn];//最短路
bool vis[maxn];
int weight[maxn];//節點重量
int queue[20 * maxn];//鬆弛佇列
int n,m;
void init()//初始化
}void spfa()
}p = edge[p].next;//下一條以u起點的邊
} head ++;
vis[u] = false;
} bool flag = true;
long long sum = 0;
for (int i = 2; i <= n; ++ i)
sum += weight[i] * dis[i];
} if (!flag)
else
printf("%lld\n", sum);
}int main()
init();
int index = 1;
for (int i = 1; i <= m; ++ i)
if (n == 0 || n == 1)
spfa();
} return 0;
}
透過現象看本質
例子 你回家的時候,發現沒帶鑰匙,你聯絡了乙個鎖匠來開鎖,結果他很快來了,並且在一分鐘之內給你開啟了鎖,問你要1000元,你會覺得很不值 但是如果乙個鎖匠用了幾個小時或者更長時間幫你開啟了鎖,你會看到他的努力,要同樣的錢,你會覺得很合理 這實際上是乙個誤區,人往往會看到一些表面的努力,而忽略了一些隱...
外觀模式 透過現象看本質
外觀模式用於為複雜系統建立乙個簡單清晰的介面。當我們需要使用到子系統的 時,為了避免過去深入地呼叫子系統 而導致後期 難以維護,減低 和子系統的耦合性,我們需要在 和子系統中引入乙個入口。實際上就是在子系統 進行一次封裝,那麼我們在呼叫子系統 的時候就可以通過呼叫封裝的方法來呼叫,以致於後期修改子系...
大道至簡之四 透過現象看本質
大道至簡 透過現象看本質 投資總結之四 時寒冰 研究趨勢是一件充滿挑戰和趣味的事情。我深信,很多現象是有規律可循的。但是,對於趨勢的判斷尤其提前做出的判斷,短期內,很多人尤其專業研究人士是無法理解的,因為,他們在專業領域迷失太久,侷限了自己的判斷。反而是很多普通投資者根據常識甚至直覺,更能洞悉本質。...