魔術球問題 題解

2021-08-25 05:44:55 字數 1825 閱讀 4855

具體的數學關係還是不會證,除了能打表發現球數規律外,內在原理也弄不清楚。

戳很難想象是一道網路流。第一感是數學。

但是看到資料範圍比較小,估計可以暴力dp。

又發現,狀態轉移比較難,狀態調整比較多,dp估計難設,又看到資料範圍又小於dp通常可做範圍,所以用同樣以規劃和狀態設計為關鍵字的,狀態調整能力更強的,複雜度可能略高的網路流來做。

實際上,這種題考點不在網路流的精深圖論,而在於網路流的規劃,計算,調整能力,也就是通常說的的建模能力。只有最後輸出方案需要一點圖論知識。

多囉嗦一句的是,網路流,建狀態同樣也有優化,盡量少的邊與點,邊權盡量更加集中(少建inf邊)會優化速度.

然後這道題首先,每個點只能選一次,這就可以用乙個套路,抱乙個點拆成一條邊權為1的邊,那麼該邊就只能經過一次了。

然後算貢獻的話,就通過原始dp來考慮。比如,寫dp就會直接轉移到乙個與自己加起來為平方和的點,那麼網路流也是可以流向一條與自己加起來為平方和的點,然後流入成功就算一次貢獻。網路流算貢獻就是向匯點t流入1的流量。

顯然dp還是可以自己創一組,就是流向乙個柱子,注意到柱子也只能被流一次,所以就用上述的套路,跟流向乙個點是一樣的。

然後源點肯定是相當於去啟用每乙個點,那麼每乙個點都可以被s啟用,所以搞乙個s流向每乙個點的流量是1的邊。

有人說跟最小點覆蓋很像,其實就是用到了鎖定乙個點只能流一次這個套路。

然後注意到,這個題說了只能選滿1-m個球,根據dp的套路就是乙個乙個考慮,然後大的只能放向小的,所以就從小的往大列舉的放就可以了,如果某乙個小的放不進當前的狀態,那麼就break。

網路流還是勝在自己的調整能力。單用點與邊來規劃處所有的情況,模擬水流,就會有著較強的調整能力,這就使得他只需用當前這張圖來表示當前的狀態,而不用像dp那樣儲存下每一種狀態。dp的調整能力也不強,當一種情況的加入會大量改變已有狀態時,dp就會顯的很麻煩,而網路流則會自動的調整了當前的狀態。目前的網路流只能通過構建邊與點的關係來構造,所有的套路很少,也只限於這乙個點與邊的圈子,而dp卻顯得更加豐富與綜合。

#include

using

namespace

std;

inline

char gc()

template

inline

void read(t&data)

return;

}template

inline

void write(r data)

const

int _ = 200001,__ = 4000;

int n,to[_<<1],head[_],cur[_],s,t,nxt[_<<1],w[_<<1],cnt=-1,vnt,ball1[_],ball2[_],reball[_];

bool vis[_];

inline

void add(register

int a,register

int b,register

int c )

int dfs(register

int now,register

int flow)

}return0;}

int main()

}ret=dfs(s,1);

memset(vis,0,sizeof(vis));

if(ret==0)

}write(ans);puts("");

for(register

int i=1;i<=ans;++i)

}}while(!vis[now]);

puts("");

}}

題解 魔術球問題

原題傳送門。一看標籤 網路流24題。我們考慮建圖,把每個點拆開,若兩個數和為平方數,那麼就從編號小的向編號大的連權值為1的有向邊。那麼就把這個問題轉換成了匹配問題。然後我們考慮對於乙個新的球,如果能找到原來在的乙個球能夠匹配,那麼可以直接匹配,否則就需要新開一根柱子。所以我們從小到大列舉放的球數,每...

魔術球問題

列舉放的球,先假設新建柱子,拆成兩個點,第乙個點連s,表示後面還可以放 第二個連t表示放到其他柱子上 再列舉放過的數和它是否組成完全平方數,列舉的數的第乙個點向它的第二個點連邊,表示這個球可以放到其他球上,容量都為一 每次跑最大流出來的表示會消掉的柱子個數,如果此時球 消去的比n大則break輸出答...

魔術球問題

題目描述 題解 個人認為網路流二十三題中比較有意思的一道。先列舉球數。每加乙個球,從 s 向 xi 連一條容量為 1 的邊,從 yi 向 t 連一條容量為 1 的邊。然後從 xi 向滿足 i j 為完全平方數的 yj 連容量為 1 的邊。在殘餘網路上跑 ek 或 dinic 如果得到的最大流為 0 ...