題目
思博貪心題寫了乙個半小時沒救了,我也沒看出這是乙個\(spfa\)來啊
設\(dp_i\)表示徹底乾掉第\(i\)只怪物的最小花費,乙個非常顯然的事情,就是對於\(k_i\)值最小的怪物滿足\(dp_i=k_i\)
非常好理解,反正到最後都要乾掉這個怪物,何必再把它乾成別的怪物
於是我們按照\(k_i\)的值先排序一下,另外維護乙個小根堆
如果堆裡沒有點或者堆頂的\(dp\)值比當前的\(k\)要大,我們直接令當前當前\(k_i\)值最小的點\(i\)的\(dp_i=k_i\),之後遍歷所有能到達點\(i\)的點\(v\),令\(s_v+=dp_i\),如果發現點\(v\)的所有出邊都被遍歷了一遍,我們就令\(dp_v=\min(s_v,k_v)\),同時把這個點加入堆中
如果堆裡有點且堆頂的\(dp\)小於於當前\(k\),就直接拿堆頂來更新
考慮這個做法的正確性,顯然當前堆中沒有節點的時候,圖中任意乙個點不可能只分解成已經處理好\(dp_i\)的點,於是我們必須引入剩下的\(k\)值最小的點
或者把堆中沒有點的情況視為初始情況,可能這樣更好理解
**
#include #define re register
#define ll long long
#define mp std::make_pair
#define min(a, b) ((a) < (b) ? (a) : (b))
const int maxn = 2e5 + 5;
struct e e[1000005];
ll dp[maxn], s[maxn], w[maxn];
int head[maxn], vis[maxn], c[maxn], p[maxn];
int n, num, top;
inline ll read()
typedef std::pairpii;
std::priority_queue, std::greater> q;
inline int cmp(int a, int b)
inline void del(int x)
}inline void add(int x, int y)
int main()
for (re int i = 1; i <= n; i++) p[i] = i;
std::sort(p + 1, p + n + 1, cmp);
int now = 1, tot = 0;
while (tot < n)
printf("%lld\n", dp[1]);
return 0;
}
AHOI2014 JSOI2014 騎士遊戲
題目背景 長期的宅男生活中,jyy又挖掘出了一款rpg遊戲。在這個遊戲中jyy會 扮演乙個英勇的騎士,用他手中的長劍去殺死入侵村莊的怪獸。題目描述 在這個遊戲中,jyy一共有兩種攻擊方式,一種是普通攻擊,一種是法術攻擊。兩種攻擊方式都會消耗jyy一些體力。採用普通攻擊進攻怪獸並不能把怪獸徹底殺死,怪...
AHOI2014 JSOI2014 騎士遊戲
傳送門 考慮 text 設 dp i 表示滅種 霧 乙隻編號為 i 的怪物的代價。那麼轉移顯然是 dp i min k i,s i sum dp 但是我們會發現這個東西是有後效性的。所以我們會想要用建圖然後跑乙個最短路什麼的來搞。於是我們觀察到上面那個 text 式子中,dp i 如果用後面那一項來...
AHOI2014 JSOI2014 宅男計畫
傳送門 我們首先要發現乙個性質 存貨天數隨買食物的次數的變化類似於單峰函式。具體證明不會啊,好像是二分加三分來證明?但是沒有找到明確的嚴格證明。感性理解一下就是 買的食物太少,很容易餓死 買太多就沒錢了,也活不長。所以我們考慮如何對於當前三分的答案如何 text 有乙個顯而易見的性質就是我們不會用 ...