CQOI2012 交換棋子 費用流

2022-06-07 03:48:08 字數 1311 閱讀 9754

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

乙個點拆三份,入點,主點,出點

入點向主點連邊,主點向出點連邊,設該點允許的交換次數為 \(x\) ,根據以下規則確定

\(s \to\) 初態點,末態點 \(\to t\),容量 \(1\),費用 \(0\)

八連通相互連邊,容量 \(\infty\),費用 \(1\)

#include using namespace std;

#define int long long

#define ll long long

#define reset(x) memset(x,0,sizeof x)

#define reset3f(x) memset(x,0x3f,sizeof x)

const int n = 1005;

namespace flow e[n];

int s, t, tans, ans, cost, ind, bus[n], qhead = 0, qtail = -1, qu[m],vis[n], dist[n];

void graph_link(int p, int q, int c, int w)

void make(int p, int q, int c, int w)

int dinic_spfa()

}return dist[t] < inf;

}int dinic_dfs(int p, int lim)

}return ret;

}void solve(int _s,int _t)

}void init()

}int n,m;

char a[n][n],b[n][n],c[n][n];

int idin(int i,int j)

int idmid(int i,int j)

int idout(int i,int j)

int check(int i,int j)

signed main()

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

else if(a[i][j]=='0' && b[i][j]=='1')

else

for(int k=i-1;k<=i+1;k++) }}

}}

flow::solve(1,2);

if(flow::ans==cnt && cnt==tot) cout

}

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

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

CQOI2012 交換棋子 網路流 費用流

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

題解 CQOI2012交換棋子

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