BZOJ 2668 cqoi2012 交換棋子

2022-04-30 11:06:06 字數 1927 閱讀 7531

time limit: 3 sec  memory limit: 128 mb

submit: 1112  solved: 409

[submit][status][discuss]

有乙個n行m列的黑白棋盤,你每次可以交換兩個相鄰格仔(相鄰是指有公共邊或公共頂點)中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能參與mi,j

次交換。

第一行包含兩個整數n,m(1<=n, m

<=20)。以下n行為初始狀態,每行為乙個包含m個字元的01串,其中0表示黑色棋子,1表示白色棋子。以下n行為目標狀態,格式同初始狀態。以下n行每行為乙個包含m個0~9數字的字串,表示每個格仔參與交換的次數上限。

輸出僅一行,為最小交換總次數。如果無解,輸出-1。

3 3110

000001

000110

100222

222222

4[submit][status][discuss]

對於每乙個格仔,拆成三個點,分別為x,y,z。

其中,x為格仔間轉移邊的入點,z為出點,y為與s和t的連線點。

s向每個原圖中黑色,新圖中白色的y點連一條容量為1,費用為0的邊,流過這條邊表示把該棋子換走替代其他棋子。

t向每個原圖中白色,新圖中黑色的y點連一條容量為1,費用為0的邊,流經這條邊表示用其他棋子把該棋子換走。

所有原圖中黑色,新圖中白色的點,x向y連容量為$\frac}$,費用為0的邊,表示至多接受這麼多替換;y向z連容量為$\frac+1}$,費用為0的邊,表示之多提供這麼多替換。所有原圖中黑色,新圖中白色的點,和這個反著連。新圖原圖中一樣的,容量則都是$\frac}$。

按照八聯通,所有相鄰點對,連線其對應為x,z即可,容量無限,費用為1,表示交換一次的代價為1。

1 #include 2

#define rep(a,b,c) for(register int a=b;a<=c;++a)

3const

int mxn = 25, siz = 500005, inf = 1e9, mv[4][2] = ,,,};

4char

a[mxn][mxn], b[mxn][mxn], c[mxn][mxn];

5int n, m, d[mxn][mxn], id[mxn][mxn][3

], id, cnt0, cnt1;

6int

s, t, tot, hd[siz], to[siz], nt[siz], fl[siz], vl[siz], dis[siz], pre[siz], que[siz], inq[siz], cost;

7 inline bool legal(int x, int y)

8 inline void add(int u, int v, int f, int

w) 12 inline bool spfa(void

) 21}22

return dis[t] 24 inline int maxflow(void

) 32

return

ret;33}

34 signed main(void

) 56 rep(i, 1, n)rep(j, 1, m)rep(k, 0, 3)if (legal(i + mv[k][0], j + mv[k][1

]))57 add(id[i][j][2], id[i + mv[k][0]][j + mv[k][1]][0], inf, 1

),58 add(id[i + mv[k][0]][j + mv[k][1]][2], id[i][j][0], inf, 1

);59 printf("

%d\n

", cnt0 == cnt1 && cnt0 == maxflow() ? cost : -1

);60 }

@author: yousiki

BZOJ2668 cqoi2012 交換棋子

題解 可以戳這裡 其實自己yy一下就知道這樣建圖的正確性了。感覺太神奇,居然還能拆成3個點 orzzzzzzzzzzzzzzzzzzzzzzzzz 跪跪跪跪跪跪跪跪 1 include2 3 include4 5 include6 7 include8 9 include10 11 include1...

bzoj2668 cqoi2012 交換棋子

description 有乙個 n 行 m 列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第 i 行第 j 列的格仔只能參與 m 次交換。input 第一行包含兩個整數 n,m 1 le n,m le 20 以下 n 行為初始狀態,每行為乙個包...

bzoj2668 cqoi2012 交換棋子

費用流題,構圖非常巧妙。考慮每個點的交換限制的約束,一看就知道是點容量,但是這裡不是一分為二,而是一分為三。首先我們把問題化簡,變成對於原圖上所有黑點,找到乙個新圖中的黑點,進行多次交換後到達。我們看到多次交換實際上是走了一條路徑 這裡不是最短路 對於這條路徑的起點和終點,僅進行了1次交換,而路徑上...