題解 魔術球問題

2021-09-13 13:57:38 字數 1619 閱讀 6956

原題傳送門。

一看標籤:網路流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 ...