洛谷P2045 方格取數加強版

2021-10-03 10:20:26 字數 1717 閱讀 7253

題目:link

網路流 - 費用流

一道比較好建模的題,重點是怎樣讓每個數隻被取一次

控制每個點被走的次數,我們可以很容易想到拆點

對於每個點,我們在入點和出點之間連兩條邊,一條流量為 1

11,費用為該格仔的權值;另一條流量為 ∞

\infty

∞,費用為 0

00。除此之外,每個點還要分別向右邊和下面的連邊,流量為 ∞

\infty

∞,費用為 000

最後,超級源點 s

ss 向點 (1,

1)

(1,1)

(1,1

) 連邊,且 (n,

n)

(n,n)

(n,n

) 向超級匯點 t

tt 連邊,流量為 k

kk,費用為 000

你也許會想到(像我一樣):如果在跑費用流時,先跑了 入點和出點之間的,流量為 ∞

\infty

∞ 的邊(也就是第一次到達方格時沒有取數)

然而,這種情況是不可能的。因為最大費用流最大流是以費用為邊權求最長路,所以一定會挑費用高的走,就不可能出現以上情況了

**:

#include

#include

#include

#include

using

namespace std;

const

int maxn=

5000+20

,maxm=

30000+10

,inf=

0x3f3f3f3f

;int nxt[maxm]

,to[maxm]

,flow[maxm]

,cost[maxm]

;int head[maxn]

,dis[maxn]

,pre[maxn]

,cur[maxn]

;bool vis[maxn]

;int n,m,k,s,t,ans;

int edgecnt=1;

inline

intread()

while

(ch>=

'0'&& ch<=

'9')s=

(s<<3)

+(s<<1)

+(ch^48)

,ch=

getchar()

;return s*w;

}inline

void

add(

int x,

int y,

int v,

int c)

inline

intid

(int x,

int y)

bool

spfa()

}}if(dis[t]

==-inf)

return0;

return1;

}void

upd(

) ans+

=cur[t]

*dis[t];}

intmain()

if(j!=m)}}

while

(spfa()

)upd()

;printf

("%d\n"

,ans)

;return0;

}

洛谷P2045 方格取數加強版

傳送門 一看題意,發現第二次取就是0了,那麼就想到了網路流 其實是看標籤 費用流建圖 1.首先s向 1,1 連一條費用為0,容量k的邊 2.然後 n,n 向t連一條費用為0,容量k的邊 3.每個點 i,j 向 i 1,j 和 i,j 1 連一條費用0,容量k的邊 此處注意判邊界 4.每個點拆成入點和...

P2045 方格取數加強版

給出乙個n n的矩陣,每一格有乙個非負整數aij,aij 1000 現在從 1,1 出發,可以往右或者往下走,最後到達 n,n 每達到一格,把該格仔的數取出來,該格仔的數就變成0,這樣一共走k次,現在要求k次所達到的方格的數的和最大 輸入格式 第一行兩個數n,k 1 n 50,0 k 10 接下來n...

P2045 方格取數加強版

簡單的拆點 拆成入點和出點,對應點之間連一條cap 1,cost x和一條cap inf,cost 0的邊,然後相鄰點的出點和其他點的入點連邊,然後s有k的流量,然後跑最大費用最大流就好了 include include include include include using namespace...