具體的數學關係還是不會證,除了能打表發現球數規律外,內在原理也弄不清楚。
戳很難想象是一道網路流。第一感是數學。
但是看到資料範圍比較小,估計可以暴力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 ...