演藝
題目背景:
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 ...