[luoguP3159] [CQOI2012]交换棋子(最小费用最大流)
传送门
好难的网络流啊,建图真的超难。
如果不告诉我是网络流的话,我估计就会写dfs了。
使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式:
将一个点分成三个点,分别为入点,原点和出点。
如果开始的图上该位置有棋子,那么从S到该点的原点连一条边权1,费用0的边
如果结束的图上该位置有棋子,那么从该点的原点到T连一条边权1,费用0的边
如果该点只在开始的图上出现,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $(v[i][j]+1)/2$ ,费用为0的边
如果该点只在结束的图上出现,那么从该点的入点向原点连一条边权为 $(v[i][j]+1)/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边
如果以上两点都不符合,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边
——byzhouyonglong
我只是题解的搬运工。
最后把每个点的原点和它相邻的点的原点连一条容量为INF,费用为0的边
#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1000001#define id(i, j, k) ((i 1) * m + j + (k 1) * n * m)using namespace std;int n, m, cnt, s, t, ans, sum1, sum2, sum;int head[N], to[N], nex[N], val[N], cost[N], dis[N], pre[N], path[N];char s1[21][21], s2[21][21], c[21][21];const int dx[8] = , dy[8] = ;bool vis[N];inline int read()inline void add(int x, int y, int z, int v)inline bool spfa()}}}return pre[t] != 1;}inline void E()int main()if(s2[i][j] == '1')if(s1[i][j] == '1' && s2[i][j] == '0')if(s1[i][j] == '0' && s2[i][j] == '1')if(s1[i][j] == s2[i][j])for(k = 0; k < 8; k++)}}if(sum1 != sum2) E();while(spfa())}if(sum != sum1) E();printf("%d\n", ans);return 0;}
下一篇:[luoguP3413] SAC#1 - 萌数(数位DP)
最小费用最大流
pla文件怎么看,pla文件用什么打开?
pl1文件怎么看,pl1文件用什么打开?
pl文件怎么看,pl文件用什么打开?
pl0文件怎么看,pl0文件用什么打开?
pkt文件怎么看,pkt文件用什么打开?
pkm文件怎么看,pkm文件用什么打开?
pks文件怎么看,pks文件用什么打开?
pka文件怎么看,pka文件用什么打开?
pkh文件怎么看,pkh文件用什么打开?
pkg文件怎么看,pkg文件用什么打开?