原題傳送門。
一看標籤:網路流24題。
我們考慮建圖,把每個點拆開,若兩個數和為平方數,那麼就從編號小的向編號大的連權值為1的有向邊。那麼就把這個問題轉換成了匹配問題。
然後我們考慮對於乙個新的球,如果能找到原來在的乙個球能夠匹配,那麼可以直接匹配,否則就需要新開一根柱子。所以我們從小到大列舉放的球數,每次加入乙個球,直到柱子個數超過給定的上限,那麼上一次就是能放的最多球數。
對於方案,我們為了方便,在新增一根柱子的時候記錄這個需要新柱子的球的編號,其餘路徑就按網路流跑二分圖匹配的路徑記錄搞一搞即可。
#include
#define maxn 20005
#define maxm 100005
#define inf 0x3f3f3f3f
using
namespace std;
template
<
typename t>
void
write
(t n)
int num, cnt =
1, s, t;
int head[maxn]
, next[maxm]
, vet[maxm]
, cost[maxm]
;void
add(
int x,
int y,
int w)
int vis[maxn]
, dep[maxn]
, cur[maxn]
, to[maxn]
, hd[maxn]
;bool
bfs(
) queue<
int> q;
q.push
(s);
vis[s]=1
; dep[s]=1
;while
(!q.
empty()
)}}}
return dep[t]
!= inf;
}int ans, tot;
intdfs
(int x,
int flow)
int used =0;
for(
int&i = cur[x]
; i; i = next[i])}
}return used;
}bool
chk(
int x)
bool
solve
(int n)
}while
(bfs()
)if(!ans) tot++
, hd[tot]
= n*2;
//新增柱子的時候記錄編號
return tot <= num;
}int
main()
} i--
;write
(i);
putchar
('\n');
int now;
for(
int j =
1; j <= num; j++
)putchar
('\n');
}return0;
}
魔術球問題 題解
具體的數學關係還是不會證,除了能打表發現球數規律外,內在原理也弄不清楚。戳很難想象是一道網路流。第一感是數學。但是看到資料範圍比較小,估計可以暴力dp。又發現,狀態轉移比較難,狀態調整比較多,dp估計難設,又看到資料範圍又小於dp通常可做範圍,所以用同樣以規劃和狀態設計為關鍵字的,狀態調整能力更強的...
魔術球問題
列舉放的球,先假設新建柱子,拆成兩個點,第乙個點連s,表示後面還可以放 第二個連t表示放到其他柱子上 再列舉放過的數和它是否組成完全平方數,列舉的數的第乙個點向它的第二個點連邊,表示這個球可以放到其他球上,容量都為一 每次跑最大流出來的表示會消掉的柱子個數,如果此時球 消去的比n大則break輸出答...
魔術球問題
題目描述 題解 個人認為網路流二十三題中比較有意思的一道。先列舉球數。每加乙個球,從 s 向 xi 連一條容量為 1 的邊,從 yi 向 t 連一條容量為 1 的邊。然後從 xi 向滿足 i j 為完全平方數的 yj 連容量為 1 的邊。在殘餘網路上跑 ek 或 dinic 如果得到的最大流為 0 ...