有乙個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的邊,最後為黑色的點與匯點連流...