JZOJ3400 GDOI2014模擬 旅行

2022-05-31 22:09:08 字數 1692 閱讀 6206

給你乙個圖,讓你選擇權值和最小的邊,使得\(1\)和\(n\),\(2\)和\(n-1\),……,\(k\)和\(n-k+1\)聯通。

\(k\leq 4\)

一看到這題就覺得特別神仙……

然後去思考網路流……

搞出了乙個最小割,後來發現這是錯的……

匆匆打了個表,獲得了這題的十分之一的分數。

其實這題有水法,許多人是全排列+\(spfa\),跑了一遍之後將路過的邊清\(0\),繼續跑。這樣貪心顯然是錯的,反例也有,但是極其水的資料居然給了他們\(100\)分!

正解是dp。

題解中有個叫做\(stenir \ tree\)的東西,感覺似乎很強大。當然我不懂,我只會dp。

現在我們是要求出乙個最小生成森林,使得一些點對聯通。

考慮一棵樹。顯然,樹的葉子節點一定是要求聯通的節點(反過來倒不一定)。

於是我們就試著dp……

設\(f_\)表示當前這棵樹的根節點為\(i\),並且\(s\)集合中的所有點連在了一起的最小代價

轉移的時候就是兩棵樹的根節點連在一起,也就是\(f_+w(i,j)+f_\to f_\)

\(s'\)是\(s\)的子集。(列舉\(s\)和\(s'\)的時間複雜度是\(3^k\)的,\(k\)表示位數,具體實現比較巧妙,見**)

然後這道題就差不多完了。注意,轉移的時候一般是\(s\)從低到高轉移,但也會向\(s\)相等的狀態轉移,這就意味著會有後效性。所以,對於同層的轉移,我們特殊地用最短路演算法來處理。

using namespace std;

#include #include #include #include inline void update(int &a,int b)

#define n 10010

#define m 10010

int n,m,k;

struct edge e[m*2];

int ne;

edge *last[n];

inline void link(int u,int v,int len);

last[u]=e+ne++;

}int f[256][n],*dis;

struct node h[1000001];

int nh;

inline bool cmph(const node &son,const node &fa)

int mn[256],ans[256];

inline bool ok(int s)

int main()

memset(f,63,sizeof f);

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

f[1update(f[s][i],f[s1][i]+ei->len+f[s-s1][ei->to]);

dis=f[s];

nh=0;

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

h[nh++]=;

while (nh);

push_heap(h,h+nh,cmph);

}} mn[s]=int_max;

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

update(mn[s],dis[i]);

} memset(ans,63,sizeof ans);

ans[0]=0;

for (int s=1;s<1<

不是什麼題都能用網路流做的……

dp也能玩出各種花樣……

JZOJ5242 GDOI模擬 矩陣

給出乙個n m 的01 矩陣,求其中有多少個連續子矩陣,使得其面積大於等於k,且其中不包含1。非常經典的一道題目。首先我們很容易知道n 3的方法。那麼我們來優化一下。我們先求出f i j 表示從 i,j 向右連續1的數量。然後把這些從大到小的插入 桶排一下 然後如果上面或下面已經有了就合併,然後算出...

JZOJ5242 GDOI2018模擬8 8 矩陣

description 給出乙個n m 的01 矩陣,求其中有多少個連續子矩陣,使得其面積大於等於k,且其中不包含1。input 第一行為用空格隔開的三個整數n,m,k。分別表示矩陣的行數,列數和子矩陣的最小面積。接下來的n 行每行為用空格隔開的m 個整數,為題目中給出的矩陣。output 輸出一行...

JZOJ5233 GDOI模擬 概率博弈

小a和小b在玩遊戲。這個遊戲是這樣的 有一棵n個點的以1為根的有根樹,葉子有權值。假設有m個葉子,那麼樹上每個葉子的權值序列就是乙個1 m 的排列。一開始在1號點有一顆棋子。兩人輪流將這顆棋子移向其當前位置的乙個兒子。假如棋子到達葉子,遊戲結束,最終獲得的權值為所在葉子對應權值。小a希望最後的權值盡...