題目描述
這個桌遊的地圖可以被抽象成乙個 n 個點,m 條邊的有向無環圖(不保證連通),小c在這個地圖上行走,小c能走到某個點當且僅當能夠到達這個點的所有點都已經被小c走到。小c會走到每個點恰好 1 次,並且他能走到哪些點與他當前所在的點沒有關係(即可以走到與當前所在的點沒有連邊的點,只要滿足之前的條件)。
小c每走到乙個標號比之前走到的點都大的點,他就會有 1/2 的概率從對手那裡拿到 1 籌碼,有 1/2 的概率給對手 1 塊籌碼,雙方初始各有 1919810 個籌碼。
小c的運氣時好時壞,所以他希望你幫他計算出:
在最優情況下,即他每次都能從對手那裡拿到籌碼時,他採取最優的行走方式能得到的籌碼數。
在最劣情況下,即對手每次都能從他那裡拿到籌碼時,他採取最優的行走方式會失去的籌碼數。
題目很容易看出來是拓撲排序,第一問也比較好像,直接
priority_queue< int,vector< int >,greater< int> >qu,維護最小的元素;
第二問就比較難了,如果直接跟第一問反過來,維護最大元素,肯定是有問題的,如圖:
發現這個圖如果貪心每次出最大點,那麼拓撲序列是 2、3、1、4 ,這個答案是3
可以把拓撲序列改為 2、1、4、3,那麼答案為2;
所以可以總結為:當入隊元素大於mmax時,把這個元素入到priority_queue佇列裡面,維護最大值,如果不大於mmax,就入到queue佇列裡面,繼續bfs;
**:
#include
#define ll long long
#define pa pair
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using
namespace std;
const
int n=
500100
;const
int m=
100000
;const ll mod=
1e9+7;
inline
intread()
while
(c>=
'0'&&c<=
'9')
return x*sign;
}int n,m,cnt,head[n]
,in1[n]
,in2[n]
;int ans1,ans2;
vector<
int>ve1;
struct nodeedge[n*2]
;void
add(
int p,
int q)
void
bfs1()
}}void
bfs2()
while
(!qu2.
empty()
)}}}
}int
main()
bfs1()
;bfs2()
;int mmax=0;
for(
int i=
0;isize()
;i++)}
cout<
cout<
return0;
}
Luogu P5603 小C與桌遊
這個題一看和入度扯上關係就是明顯的topo了。對於最優情況,直接維護小根堆,貪心即可。對於最劣情況,顯然直接維護大根堆然後貪心是錯誤的 反例見luogu題解 所以每次要取出所有能拓展的節點,依次加入佇列topo即可。這裡注意當連到的點比當前最大值大時,壓入大根堆,否則加入佇列。code includ...
洛谷P5603 小C與桌遊
題目鏈結 小c是乙個熱愛桌遊的高中生,現在他被乙個桌遊難住了,快來幫幫他!這個桌遊的地圖可以被抽象成乙個 n 個點,m 條邊的有向無環圖 不保證連通 小c在這個地圖上行走,小c能走到某個點當且僅當能夠到達這個點的所有點都已經被小c走到。小c會走到每個點恰好 1 次,並且他能走到哪些點與他當前所在的點...
洛谷10月月賽 III 小C與桌遊
該問題可以分為兩個子問題 1.求一種拓撲順序使點的編號最大值的更新次數最多。2.求一種拓撲順序使點的編號最大值的更新次數最少。對於第乙個子問題,我們貪心的想,每次走到所有能走的點中編號最小的點。這種貪心顯然是正確的,因為如果我們先走編號較大的點,再走編號較小的點,顯然不如先走編號較小的點更優一些。所...