【問題描述】
很久很久以前有乙個國家,這個國家有n個城市,城市由1,2,3,…,n標號,城市間有m條雙向道路,每條道路都有兩個屬性g和s,兩個城市間可能有多條道路,並且可能存在將某一城市與其自身連線起來的道路。後來由於戰爭的原因,國王不得不下令減小花費從而關閉一些道路,但是必須要保證任意兩個城市相互可達。
道路花費的計算公式為wg*max+ws*max,其中wg和ws是給定的值。國王想要在滿足連通性的前提下使這個花費最小,現在需要你計算出這個花費。
【輸入格式】
輸入檔名為road.in。
第一行包含兩個正整數n和m。第二行包含兩個正整數wg和ws。
後面的m行每行描述一條道路,包含四個正整數u,v,g,s,分別表示道路連線的兩個城市以及道路的兩個屬性。
【輸出格式】
輸出檔名為road.out。
輸出乙個整數,表示最小花費。若無論如何不能滿足連通性,輸出-1。
【輸入輸出樣例】
road.in
3 3road.out 【資料規模與約定】2 1
1 2 10 15
1 2 4 20
1 3 5 1
對於10%的資料,n≤10,m≤20;對於30%的資料,n≤100,m≤1000;對於50%的資料,n≤200,m≤5000;
對於100%的資料,n≤400,m≤50000,wg,ws,g,s≤1000000000。
分析:最小生成樹問題,只不過有兩個量對答案有影響.這種題不可能同時考慮兩個量,要消除乙個量的影響,就先按照g的大小排序.由於g是排好序的,從小到大列舉邊,然後求最小生成樹,這就是主要的思路.
這個演算法的瓶頸就在於每次插入一條邊都要對所有的邊排序做最小生成樹,非常耗時間.因為有很多邊經常被用到,我們可以在處理的時候把它們維護成有序的,這個時候只需要考慮s的大小就可以了,因為max的大小是已知的.每次不用排序了,但是在這麼多點中做克魯斯卡爾演算法還是比較慢.
如果新加入一條邊,那麼組成最小生成樹的n條邊一定是原來最小生成樹的n-1條邊和這條新加進來的邊中取n-1條邊.因為沒有選到原來的最小生成樹的邊一定沒有最小生成樹上的邊優,新加進來的這條邊由於不知道它s的具體大小,所以可能在最小生成樹中,這樣維護乙個n條邊的邊集,每次在上面求最小生成樹就可以了.
兩個因素互相影響的可以先想辦法消除其中乙個因素的影響,再來考慮另外乙個因素的影響.
#include #include#include
#include
using
namespace
std;
typedef
long
long
ll;const ll inf = 1ll << 60
;ll n, m, wg, ws, fa[
510], top, tree[510], ans =inf;
struct
node
e[50010
];bool
cmp(node a, node b)
ll find(ll x)
intmain()
top++;
if (cur ==top)
tree[cur] =i;
else
int num = 0
;
for (int j = 1; j <= top; j++)
}if (num == n - 1 &&flag) //如果第i條邊的g為最大的g,那麼這條邊肯定要被選到
ans = min(ans, wg*e[i].g + ws*e[tree[num]].s);
top =num;
}if (ans ==inf)
printf("-1
");else
printf(
"%lld\n
", ans);
return0;
}
NOIP模擬 保留道路
很久很久以前有乙個國家,這個國家有 n 個城市,城市由 1,2,3,n 標號,城市間有 m 條雙向道路,每條道路都有兩個屬性 g 和 s 兩個城市間可能有多條道路,並且可能存在將某一城市與其自身連線起來的道路。後來由於戰爭的原因,國王不得不下令減小花費從而關閉一些道路,但是必須要保證任意兩個城市相互...
noip模擬賽 道路分組
分析 因為每一組編號都是連續的嘛,所以能分成一組的盡量分,每次加邊後dfs判斷一下1和n是否連通.有向圖的判連通沒有什麼很快的方法,特別注意,並查集是錯的!這個演算法可以得到60分.事實上每一次都不需要從點1開始dfs,因為之前很多點都遍歷到了,再從1開始會重複.如果新加的一條邊的起點沒有被訪問過,...
noip模擬賽 密碼
表示沒看懂演算法3 問題描述 有壓迫,就有反抗。mored的寵物在法庭的幫助下終於反抗了。作為乙隻聰明的寵物,他打算把魔法使mored的魔法書盜去,奪取mored的魔法能力。但mored怎麼會讓自己的魔法書輕易地被盜取?mored在魔法書上設定了乙個密碼鎖,密碼鎖上有乙個問題。施以斯臥鋪魔法吧,你有...