網路流24題 魔術球問題 最大流

2022-03-25 21:28:17 字數 1679 閱讀 4735

洛谷傳送門

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.我們二分答案,每次...