bzoj2668 cqoi2012 交換棋子

2022-06-01 09:33:15 字數 1635 閱讀 6919

費用流題,構圖非常巧妙。

考慮每個點的交換限制的約束,一看就知道是點容量,但是這裡不是一分為二,而是一分為三。

首先我們把問題化簡,變成對於原圖上所有黑點,找到乙個新圖中的黑點,進行多次交換後到達。我們看到多次交換實際上是走了一條路徑(這裡不是最短路)。對於這條路徑的起點和終點,僅進行了1次交換,而路徑上的其他點都交換了2次。所以我們需要構造一種圖來把這個交換次數的差異體現出來,於是:

對於每個點一分為三,分為p0,p1,p2,對於每個點,如果它是原圖中得黑點,連邊,,;如果它是新圖中得黑點,連邊,,;如果它在兩個圖中都是白點,那麼連邊,。這樣就可以體現出點容量的差異了。

然後對於原圖中可以交換的兩個點(i,j)連線,那麼這種邊每流過1的流量就意味著(i,j)交換了一次,那麼費用就是最終的答案了。

chess

1 #include2 #include3 #include4 #include5 #include6

#define maxn 2000

7#define maxm 50000

8#define inf 2147483647

9using

namespace

std;

10struct

et11

e[maxm];

14char s1[100][100],s2[100][100],s3[100][100

];15

int a[100][100],b[100][100],c[100][100],num[100][100

];16

intfir[maxn],q[maxm],d[maxn],pre[maxn];

17bool

inque[maxn];

18int

n,m,st,ed,tot,ans,b1,b2,fare;

1920

bool

find()

2137

}38 inque[now]=0;39

}40return d[ed]

4243

void

fare_flow()

4454

}

5556

void add(int x,int y,int z,int

w)57

6162

intmain()

6383

for (int i=1;i<=n;i++)

84for (int j=1;j<=m;j++)

8594

else

95if

(b[i][j])

96101

else

102106

}107

for (int i=1;i<=n;i++)

108for (int j=1;j<=m;j++)

109119

//for (int i=2;i<=tot;i++) cout<120 fare=0

;121

if (b1==b2)

125else fare=-1

;126 printf("

%d\n

",fare);

127return0;

128 }

BZOJ 2668 cqoi2012 交換棋子

time limit 3 sec memory limit 128 mb submit 1112 solved 409 submit status discuss 有乙個n行m列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能...

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 行為初始狀態,每行為乙個包...