省選模擬(12 08) T2 演藝

2021-08-13 19:02:48 字數 3102 閱讀 7790

演藝

題目背景:

12.08 

省選模擬t2

分析:最短路

+ 拓撲排序

+ bitset + 雜湊

感覺是本場最難的題······考慮如何為滿足條件的a,

b,就是在s à

t的最短路

dag上,經過a的

s àt的方案數與經過b的

s àt之和是s à

t的總方案數,並且

a不能到

b。考慮如何實現,首先我們以

s為起點跑

dijkstra

,獲得每乙個點的

dis,如果滿足

dis[e->u] + e->w = dis[e->v]

,那麼這條邊

e就在最短路

dag上,我們可以由此進行拓撲排序,然後根據拓撲序,分別求出從

s出發,只經過最短路徑圖上的邊,到點

i的方案數

x,和從

t出發,只經過最短路徑圖上的邊的反向邊,到點

i的方案數

y,那麼最終的經過i的從

s到t的最短路徑數字

x * y

,因為數值過大,所以需要

hash

一下,這樣之後,對於每乙個點

i,可能的可以成對的點的

hash

值是固定的,那麼我們只需要放到乙個

map / hash_map

中統計一下出現次數就可以了(**使用了雙雜湊,所以用

map方便一些),顯然,這樣的答案算進了某些不合法方案,因為並沒有判斷是否符合

a不能到

b這個條件,首先,我們可以將

hash

值標號,將每乙個

hash

值對應的節點有哪些,將狀態壓到乙個

bitset

裡面,同樣,利用拓撲序和

bitset

,求得每乙個點在

s到它的最短路徑上會經過的點,然後將每乙個方案數的

hash

值為點i

對應的可行點的

hash

值的點集,與可以到達點

i的點的點集的重合部分減去即可,注意這一步只能針對在最短路

dag上的點。

source:

/*

created by scarlyw

*/#include #include #include #include #include #include #include #include #include #include #include #include #include inline char read()

return *s++;}/*

templateinline void r(t &x)

for (x = 0; isdigit(c); c = read())

x = ((x << 2) + x << 1) + (c ^ '0');

if (iosig) x = -x;

}//*/

const int out_len = 1024 * 1024;

char obuf[out_len], *oh = obuf;

inline void write_char(char c)

templateinline void w(t x)

}inline void flush()

///*

templateinline void r(t &x)

//*/

const int maxn = 50000 + 10;

const long long inf = 1000000000000000000;

int n, m, s, t, x, y, z, cnt;

long long dis[maxn];

struct node

inline bool operator < (const node &a) const

} ;std::vectoredge[maxn];

inline void add_edge(int x, int y, int z)

inline void read_in()

inline void dijkstra(int s) }}

bool vis[maxn];

std::vectortop;

inline void dfs(int cur)

top.push_back(cur);

}int d[maxn];

std::pairhash[maxn], hash1[maxn], hash2[maxn], need;

const int mod1 = 1000000000 + 7, mod2 = 1000000000 + 9;

inline void solve_hash()

for (int i = 1; i <= n; ++i) if (d[i] == 0) dfs(i);

for (int i = 1; i <= n; ++i)

hash[i] = hash1[i] = hash2[i] = std::make_pair(0, 0);

hash1[s] = std::make_pair(1, 1);

for (int i = top.size() - 1; i >= 0; --i)

} }hash2[t] = std::make_pair(1, 1);

for (int i = 0; i < top.size(); ++i)

} }for (int i = 1; i <= n; ++i)

}std::map, int> mp, id;

std::bitsetreach[maxn], able[maxn], bit;

inline void solve_ans()

for (int i = 1; i <= n; ++i)

for (int i = top.size() - 1; i >= 0; --i)

} for (int cur = 1; cur <= n; ++cur)

std::cout << ans;

}int main()

省選模擬2

前 n 個正整數劃分成 m 個集合,不存在乙個分解線使得劃分出來的值域分開 那麼設 f 表示將前 i 數劃分到 j 個集合裡,其中還剩 k 個集合沒有達到最大值 那麼答案就是 f 邊界 f 1 對於 i neq0,n f 0 轉移的話分別考慮是否新開乙個集合,是否讓乙個集合達到最大值 f f f k...

省選模擬2 題解

暴力插頭dp 網路流判斷可行性,可以拿到85分。然而這個題看起來就很像無限之環,只要稍微改一下建圖就好了。然而這個建圖還蠻難想到的。因為不會做 看不懂題解 std太長,所以咕掉了。70分部分分 考慮到狀態數很少,直接暴力狀壓dp就好了 可以用vector map記錄狀態 然而題解第一步的轉化題意就很...

省選模擬(12 08) T3 圈圈圈圈圈圈圈圈

圈圈圈圈圈圈圈圈 題目背景 12.08 省選模擬t3 分析 dp 定義f i j 表示列舉到第 i個家族,有 j個人沒有被匹配,那麼列舉第 i 1 個家族中有多少人用於和這 j個人匹配,轉移方程 f i 1 j a i 1 x 2 f i j c j,x c a i 1 x x 意義為,從 a i ...