有n個柱子,編號為1,2…….的小環,要將它們依次套在環上,要求直接接觸的兩小球的和為完全平方數,那麼最多可以套幾個小球。
首先可以貪心,如果可以套在其他小球上,則套在其他小球上,反之,套在柱子上,直到沒有多餘柱子,可以證明這是對的,但我覺得還是網路流的做法比較重要。
因為要依次取小球,那麼當答案為ans時,編號為1-ans的小球都被取走,我們可以用類似於洛谷 p1251 餐巾計畫問題的做法來拆點建圖。
將每個點拆成a,b兩點,因為放環有兩種可能,從s連一條邊到a,流量為1,表示直接將小球放在柱子底部,a再向t連一條流量為1的邊,保證該小球已經用過了,s向b連一條流量為1的邊,因為該小球並不會隨著它流到匯點而消失,b向編號大於它的且滿足和為完全平方數的點的a連邊,表示在這個小球上放小球。最後s向s連一條流量為柱子數的邊,用於限制柱子數。
在實際操作時,因為並不知道答案為多少,為了保證它能依次被取走,故要列舉小球個數,不斷的在殘餘網路上加入有關第i個小球的邊,並在參與網路的基礎上求最大流,若最大流不等於i,說明i-1為最優解。因為除了s->s的邊外,邊權均為一,因而可以列舉邊來計算流量。
另外此題不可以二分答案來做,因為從小到大列舉小球個數時可以利用殘餘網路加速,而二分則每次都要重新建圖,反而更劣。
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define n 4100
using
namespace
std;
int n,m,bb,first[n],deep[n],tmp,s,t,sum,ans,cur[n];
bool out[n];
struct bn
bn[200100];
queue
que;
inline
void add(int u,int v,int w)
inline
void ad(int u,int v,int w)
inline
bool bfs()
}return deep[t];
}int dfs(int now,int mn)
int res;
for(int &p=cur[now]; p!=-1; p=bn[p].next)
}return0;}
int main()
}ad(s,0,n);
for(i=1; i<=2000; i++)
if(ans!=i) break;
}cout
<1
printf("%d ",j);
for(q=j;;)
}if(p==-1) break;
}puts("");
}}
洛谷P2765 魔術球問題
問題描述 假設有n根柱子,現要按下述規則在這n根柱子中依次放入編號為1,2,3,的球。1 每次只能在某根柱子的最上面放球。2 在同一根柱子中,任何2個相鄰球的編號之和為完全平方數。試設計乙個演算法,計算出在n根柱子上最多能放多少個球。例如,在4 根柱子上最多可放11 個球。程式設計任務 對於給定的n...
洛谷 P2765 魔術球問題
問題描述 假設有n根柱子,現要按下述規則在這n根柱子中依次放入編號為1,2,3,的球。1 每次只能在某根柱子的最上面放球。2 在同一根柱子中,任何2個相鄰球的編號之和為完全平方數。試設計乙個演算法,計算出在n根柱子上最多能放多少個球。例如,在4 根柱子上最多可放11 個球。程式設計任務 對於給定的n...
P2765 魔術球問題
題目描述 問題描述 假設有n根柱子,現要按下述規則在這n根柱子中依次放入編號為1,2,3,的球。1 每次只能在某根柱子的最上面放球。2 在同一根柱子中,任何2個相鄰球的編號之和為完全平方數。試設計乙個演算法,計算出在n根柱子上最多能放多少個球。例如,在4 根柱子上最多可放11 個球。程式設計任務 對...