洛谷傳送門
loj傳送門
腦抽寫了個費用流$t$飛了,看了題解才明白是怎麼跑最大流的
這道題有乙個貪心,如果小於它的數沒有能和它之和是完全平方數的,那麼它一定要新建乙個柱子
證明可以看poorpool神犇的這篇部落格
由於每個點只能用一次,所以每個點$x$拆成$2$個點$x1$和$x2$,$x1$和源點相連,$x2$和匯點相連,流量均為$1$
而如果兩個數$x,y$能構成完全平方數,那麼$x1$連線$y2$
我們從小到大遍歷每個數$x$,然後在圖內加入$x2$,如果產生了一條新流,說明$x$能找到乙個$y(y否則,我們新加入乙個柱子
然後不論能否產生新流,把$x1$加入到圖中
驗證是否產生新流可以用$dinic$最大流實現
為什麼要這麼做呢?
我們是動態往圖裡加的點,每次加完點以後,如果情況合法,會產生一條新流。
如果不這麼做,我們每次要重新建邊,大大拉高的時間複雜度
如何記錄方案呢?
乙個柱子裡的點會形成一條鏈(即使在網路流圖內它看起來不是一條鏈)。
可以向並查集一樣,開乙個陣列,在$dinic$裡記錄每個點的流量流向哪個位置就行了
1 #include 2 #include 3 #include 4 #include 5#define n1 8010
6#define m1 40010
7#define ll long long
8#define dd double
9#define inf 0x3f3f3f3f
10using
namespace
std;
1112
intgint()
1316
while(c>='
0'&&c<='9')
17return ret*fh;18}
19struct
edge
26}e,e;
27int
n,m,k,s,t,f,mx;
28int
que[m1],hd,tl,dep[n1],cur[n1],pre[n1];
29int
bfs()
3043}44
return dep[t]!=-1;45
}46int dfs(int x,int
limit)
4759}60
return
ans;61}
6263
intstk[n1],tp;
6465
intde;
66int
dinic()
6773
void
solve()
7486 e.ae(i+mx,t,1); e.ae(t,i+mx,0
); 87
if(dinic()<=0
)89 stk[++tp]=i; num++;90}
91 e.ae(s,i,1); e.ae(i,s,0
); 92
}93 printf("
%d\n
",ans);
94for(i=1;i<=n;i++)
95100
}101
102int
main()
103
網路流24題 魔術球問題
列舉答案轉化為判定性問題,然後最小路徑覆蓋,可以轉化成二分圖最大匹配,從而用最大流解決。列舉答案a,在圖中建立節點1.a。如果對於i具體方法可以順序列舉a的值,當最小路徑覆蓋數剛好大於n時終止,a 1就是最優解。由於是順序放球,每根柱子上的球滿足這樣的特徵,即下面的球編號小於上面球的編號。抽象成圖論...
魔術球問題(網路流24題)
假設有n根柱子,現要按下述規則在這n根柱子中依次放入編號為1,2,3,的球。1 每次只能在某根柱子的最上面放球。2 在同一根柱子中,任何2個相鄰球的編號之和為完全平方數。試設計乙個演算法,計算出在n根柱子上最多能放多少個球。例如,在4 根柱子上最多可放11 個球。對於給定的n,計算在n根柱子上最多能...
網路流24題 魔術球問題
以珠子為點,滿足條件就兩兩連邊 那麼就是讓你求n條路徑最多能覆蓋多少節點。眾所周知,最小邊覆蓋 點總數 最大匹配 不會看這裡link 於是拆點跑二分圖即可 大概就是s向x連邊 滿足條件的點k向x 連邊 x 向t連邊 有兩種方式 1.我們輪流加點,每次在殘量網路跑最大流就可以了 2.我們二分答案,每次...