(注意相鄰交換指的是八連通)
顯然可以將黑白交換看做只有黑色棋子在空棋盤上移動
交換限制交給流量,那麼有代價自然就是費用流了
考慮直接將兩個相鄰格仔連起來,由於交換次數是相對單個格仔而言的,流量無法確定
既然交換次數是單個格仔的屬性,自然可以考慮到拆點來表示其屬性
考慮將乙個格仔拆成入點和出點,中間連一條邊,流量為交換次數;但是想象乙個黑色棋子從1->2->3,那麼中間格仔用了兩次,兩邊格仔只用了一次,這個路徑就沒法用兩個點表示了
繼續拆,拆成三個點,入點出點和中間點,中間點即為黑色格仔所在位置,移動操作相當於中間點->出點->入點->中間點;我們在中間點->出點,入點->中間點這兩個地方限流;
發現如果乙個位置初始是黑點,最終是白點,那麼出去的流量顯然為進來的流量+1,其餘同理
所以將交換次數平分給進來和出去兩個地方,分情況討論「1」的分配
其他的邊很好想,連好後跑一次mcmf即可
#include#define n 2005
#define m 200005
using namespace std;
const int inf = 100000000;
int n,m,s,t,maxflow,mincost;
int pre[n],preedge[n],flow[n];
int exist[n],dis[n];
int dox[8]=;
int doy[8]=;
char st[25][25],ed[25][25],lim[25][25];
struct edge
edge[m<<1];int head[n],cnt=1;
void add_edge(int from,int to,int flow,int dis)
void add(int from,int to,int flow,int dis)
int get_id(int x,int y,int c)
bool spfa()
}} }
return (pre[t] != -1);
}void mcmf() }}
int main()
else if(st[i][j-1]=='0' && ed[i][j-1]=='1')
else
//八連通
for(int k=0;k<8;++k)
}} mcmf();
if(maxflow != sum) cout<<-1
}
題解 CQOI2012交換棋子
感受到網路流的強大了 這道題目的關鍵在於 前後顏色不變的,流入流出的次數相等 原本是黑色的最後變成了白色,流出比流入次數多1 原本是白色最後變成黑色,流入比流出次數多一。所以我們將每一點拆成3個點,分別代表流入點,原點與流出點。最開始為黑色的點與源點連流量為1,費用為0的邊,最後為黑色的點與匯點連流...
CQOI2012 交換棋子 費用流
有乙個n行m列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能參與mi,j次交換。乙個點拆三份,入點,主點,出點 入點向主點連邊,主點向出點連邊,設該點允許的交換次數為 x 根據以下規則確定 s to 初態點,末態點 to t...
CQOI2012 交換棋子 網路流 費用流
有乙個n行 m列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能參與mi j次交換。第一行包含兩個整數n,m 1 n,m 20 以下n 行為初始狀態,每行為乙個包含 m個字元的 01串,其中 0表示黑色棋子,1表示白色棋子。以...