CQOI2012 交換棋子 網路流 費用流

2022-05-29 06:18:10 字數 1559 閱讀 5827

有乙個n行

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

,j次交換。

第一行包含兩個整數n,

m(1≤

n,m≤

20)。以下n

行為初始狀態,每行為乙個包含

m個字元的

01串,其中

0表示黑色棋子,

1表示白色棋子。以下

n行為目標狀態,格式同初始狀態。以下n行每行為乙個包含m個

0..9

數字的字串,表示每個格仔參與交換的次數上限。

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

。一眼費用流系列…然而這題的處理有點詭異,首先要拆點將點的限制轉化為邊的限制,s→

ini,

outi

→t。i

n→ou

t的權值是多少?分三種情況討論:

既不是起始也不是結束狀態:⌊n

2⌋既是起始也是結束狀態:⌊n

+22⌋

是起始或結束狀態:⌊n

+12⌋

#include 

using

namespace

std;

const

int maxn = 2005;

struct node edge[maxn*40];

int head[maxn], top = 0;

void push(int i, int j, int k, int l)

, head[i] = top;

++top, edge[top] = (node) , head[j] = top;

}int vis[maxn], dis[maxn], s = 2001, t = 2002;

queue

que;

int pre[maxn], pre_edge[maxn];

const

int inf = 233333333;

bool spfa()

}return dis[t] < inf;

}int sap(int &cost)

int mst(int &cost)

int n, m;

int a[30][30], b[30][30], c[30][30];

char str[30];

int readln(int a[30][30])

return cnt;

}inline

int number(int i, int j, int id)

int dx = , dy = ;

int main()

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

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

int ans = 0, cost = 0;

ans = mst(cost);

if (ans == a) else

puts("-1");

return

0;}

CQOI2012 交換棋子 費用流

有乙個n行m列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能參與mi,j次交換。乙個點拆三份,入點,主點,出點 入點向主點連邊,主點向出點連邊,設該點允許的交換次數為 x 根據以下規則確定 s to 初態點,末態點 to t...

題解 CQOI2012交換棋子

感受到網路流的強大了 這道題目的關鍵在於 前後顏色不變的,流入流出的次數相等 原本是黑色的最後變成了白色,流出比流入次數多1 原本是白色最後變成黑色,流入比流出次數多一。所以我們將每一點拆成3個點,分別代表流入點,原點與流出點。最開始為黑色的點與源點連流量為1,費用為0的邊,最後為黑色的點與匯點連流...

CQOI2012 交換棋子(拆點 費用流)

注意相鄰交換指的是八連通 顯然可以將黑白交換看做只有黑色棋子在空棋盤上移動 交換限制交給流量,那麼有代價自然就是費用流了 考慮直接將兩個相鄰格仔連起來,由於交換次數是相對單個格仔而言的,流量無法確定 既然交換次數是單個格仔的屬性,自然可以考慮到拆點來表示其屬性 考慮將乙個格仔拆成入點和出點,中間連一...