传送门

解题思路

  神仙题。调了一个晚上+半个上午。。这道咋看咋都不像图论的题竟然用费用流做,将行+列为奇数的点和偶数的点分开,也就是匹配问题,然后把一个点复制四份,分别代表这个点的上下左右接头,如果有这个接头就加一个费用为\(0\),流量为\(1\)的边,如果没有要分情况讨论,因为从源点到这个点的流量是固定的,当只有一个接头时,可以让这个点向自己其余三个点连费用为\(1\),流量为\(1\)的边,当有两个接头并且两个接头相邻时,让这个点的两个接头分别与对应的方向连边,当有三个接头时,让那个没有的接头向相邻的连费用为\(1\)的边,向相对的连费用为\(2\)的边。然后一边费用流就行了。代码比较丑。建图写挫了。。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib> using namespace std;
const int MAXN = 10005;
const int MAXM = 100005;
const int inf = 0x3f3f3f3f;
const int zz[4] = {1,2,4,8}; // 0 1 2 3 inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='0'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
} int n,m,head[MAXN],to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1],cost[MAXM<<1],pre[MAXN];
int S,T,cnt=1,maxflow,ans,dis[MAXN],ch[MAXN][5],num,tot,sum,pos[2005][2005];
int incf[MAXN],all;
bool vis[MAXN];
queue<int> Q; inline void add(int bg,int ed,int z,int w){
to[++cnt]=ed,nxt[cnt]=head[bg],val[cnt]=z,cost[cnt]=w,head[bg]=cnt;
} inline void solve1(int p,int x,int op){
for(int i=0;i<=3;i++)
if((x&zz[i])) {
if(op&1) add(p,ch[p][i],1,0),add(ch[p][i],p,0,0);
else add(ch[p][i],p,1,0),add(p,ch[p][i],0,0);
if(i<2) {
if(op&1) add(p,ch[p][i+2],1,2),add(ch[p][i+2],p,0,-2);
else add(ch[p][i+2],p,1,2),add(p,ch[p][i+2],0,-2);
}
else {
if(op&1) add(p,ch[p][i-2],1,2),add(ch[p][i-2],p,0,-2);
else add(ch[p][i-2],p,1,2),add(p,ch[p][i-2],0,-2);
}
if(op&1){
add(p,ch[p][(i+1)%4],1,1),add(ch[p][(i+1)%4],p,0,-1);
add(p,ch[p][(i+3)%4],1,1),add(ch[p][(i+3)%4],p,0,-1);
}
else{
add(ch[p][(i+1)%4],p,1,1),add(p,ch[p][(i+1)%4],0,-1);
add(ch[p][(i+3)%4],p,1,1),add(p,ch[p][(i+3)%4],0,-1);
}
}
} inline void solve2(int p,int x,int op){
if(x==5 || x==10){
for(int i=0;i<=3;i++)
if(x&zz[i]){
if(op&1) add(p,ch[p][i],1,0),add(ch[p][i],p,0,0);
else add(ch[p][i],p,1,0),add(p,ch[p][i],0,0);
}
return ;
}
for(int i=0;i<=3;i++){
if(x&zz[i]){
if(op&1) add(p,ch[p][i],1,0),add(ch[p][i],p,0,0);
else add(ch[p][i],p,1,0),add(p,ch[p][i],0,0);
}
else{
if(i<2) {
if((op&1))
add(ch[p][i+2],ch[p][i],1,1),add(ch[p][i],ch[p][i+2],0,-1);
else
add(ch[p][i],ch[p][i+2],1,1),add(ch[p][i+2],ch[p][i],0,-1);
}
else {
if((op&1))
add(ch[p][i-2],ch[p][i],1,1),add(ch[p][i],ch[p][i-2],0,-1);
else
add(ch[p][i],ch[p][i-2],1,1),add(ch[p][i-2],ch[p][i],0,-1);
}
}
}
} inline void solve3(int p,int x,int op){
for(int i=0;i<=3;i++){
if(x&zz[i]){
if(op&1) add(p,ch[p][i],1,0),add(ch[p][i],p,0,0);
else add(ch[p][i],p,1,0),add(p,ch[p][i],0,0);
}
else {
if((op&1)){
add(ch[p][(i+1)%4],ch[p][i],1,1);
add(ch[p][i],ch[p][(i+1)%4],0,-1);
add(ch[p][(i+3)%4],ch[p][i],1,1);
add(ch[p][i],ch[p][(i+3)%4],0,-1);
if(i<2) {
add(ch[p][i+2],ch[p][i],1,2);
add(ch[p][i],ch[p][i+2],0,-2);
}
else {
add(ch[p][i-2],ch[p][i],1,2);
add(ch[p][i],ch[p][i-2],0,-2);
}
}
else{
add(ch[p][i],ch[p][(i+1)%4],1,1);
add(ch[p][(i+1)%4],ch[p][i],0,-1);
add(ch[p][i],ch[p][(i+3)%4],1,1);
add(ch[p][(i+3)%4],ch[p][i],0,-1);
if(i<2) {
add(ch[p][i],ch[p][i+2],1,2);
add(ch[p][i+2],ch[p][i],0,-2);
}
else {
add(ch[p][i],ch[p][i-2],1,2);
add(ch[p][i-2],ch[p][i],0,-2);
}
}
}
}
} inline void solve4(int p,int op){
for(int i=0;i<=3;i++){
if(op&1) add(p,ch[p][i],1,0),add(ch[p][i],p,0,0);
else add(ch[p][i],p,1,0),add(p,ch[p][i],0,0);
}
} bool spfa(){
while(Q.size()) Q.pop();
memset(dis,0x3f,sizeof(dis));
memset(vis,false,sizeof(vis));
vis[S]=1;dis[S]=0;incf[S]=inf;Q.push(S);
while(Q.size()){
int x=Q.front();Q.pop();vis[x]=0;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(dis[u]>cost[i]+dis[x] && val[i]) {
dis[u]=cost[i]+dis[x];
incf[u]=min(incf[x],val[i]);
pre[u]=i;
if(!vis[u]) vis[u]=1,Q.push(u);
}
}
}
return (dis[T]==inf)?false:true;
} inline void update(){
int x=T,i;
while(x!=S){
i=pre[x];
val[i]-=incf[T];
val[i^1]+=incf[T];
x=to[i^1];
}
maxflow+=incf[T];
ans+=incf[T]*dis[T];
} int main(){
n=rd(),m=rd();S=++num;T=++num;int x,p;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
x=rd();p=++num;pos[i][j]=p;
for(int k=0;k<=3;k++) ch[p][k]=++num;
tot=__builtin_popcount(x);
if((i+j)&1) add(S,p,tot,0),add(p,S,0,0);
else add(p,T,tot,0),add(T,p,0,0);
if(tot==1) solve1(p,x,i+j);
else if(tot==2) solve2(p,x,i+j);
else if(tot==3) solve3(p,x,i+j);
else solve4(p,i+j);
sum+=tot;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(!((i+j)&1)) continue;
if(i!=1){
add(ch[pos[i][j]][0],ch[pos[i-1][j]][2],1,0);
add(ch[pos[i-1][j]][2],ch[pos[i][j]][0],0,0);
}
if(j!=1){
add(ch[pos[i][j]][3],ch[pos[i][j-1]][1],1,0);
add(ch[pos[i][j-1]][1],ch[pos[i][j]][3],0,0);
}
if(i!=n){
add(ch[pos[i][j]][2],ch[pos[i+1][j]][0],1,0);
add(ch[pos[i+1][j]][0],ch[pos[i][j]][2],0,0);
}
if(j!=m){
add(ch[pos[i][j]][1],ch[pos[i][j+1]][3],1,0);
add(ch[pos[i][j+1]][3],ch[pos[i][j]][1],0,0);
}
}
if(sum&1) {puts("-1");return 0;}
sum>>=1;
while(spfa()) update();
if(maxflow!=sum) puts("-1");
else printf("%d\n",ans);
return 0;
}

BZOJ 5120: [2017国家集训队测试]无限之环(费用流)的更多相关文章

  1. bzoj 5120 [2017国家集训队测试]无限之环——网络流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5120 旋转的话相当于去掉一个插头.新增一个插头,所以在这两个插头之间连边并带上费用即可. 网 ...

  2. bzoj 5120: [2017国家集训队测试]无限之环【最小费用最大流】

    玄妙的建图-- 这种平衡度数的题按套路是先黑白染色然后分别连ST点,相邻格子连黑向白连费用1流量0的边,然后考虑费用怎么表示 把一个点拆成五个,上下左右中,中间点黑白染色连ST, 对于连S的点,中点连 ...

  3. BZOJ5120 [2017国家集训队测试]无限之环 费用流

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ5120 题意概括 原题挺简略的. 题解 本题好难. 听了任轩笛大佬<国家队神犇>的讲课才 ...

  4. [BZOJ5120] [2017国家集训队测试]无限之环

    Description 曾经有一款流行的游戏,叫做InfinityLoop,先来简单的介绍一下这个游戏: 游戏在一个n×m的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中 ...

  5. BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)

    题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...

  6. BZOJ_2622_[2012国家集训队测试]深入虎穴_最短路

    BZOJ_2622_[2012国家集训队测试]深入虎穴_最短路 Description 虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物 ...

  7. 【BZOJ2622】[2012国家集训队测试]深入虎穴 次短路

    [BZOJ2622][2012国家集训队测试]深入虎穴 Description 虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物,例如“ ...

  8. 2017国家集训队作业Atcoder题目试做

    2017国家集训队作业Atcoder题目试做 虽然远没有达到这个水平,但是据说Atcoder思维难度大,代码难度小,适合我这种不会打字的选手,所以试着做一做 不知道能做几题啊 在完全自己做出来的题前面 ...

  9. 2017国家集训队作业[agc016b]Color Hats

    2017国家集训队作业[agc016b]Color Hats 题意: 有\(N\)个人,每个人有一顶帽子.帽子有不同的颜色.现在,每个人都告诉你,他看到的所有其它人的帽子共有多少种颜色,问有没有符合所 ...

随机推荐

  1. 在 MacBook 上安装 Ubuntu

    建立ubuntu 安裝U盤,加入usb port,按住option key 開機,正常安裝. 完成後,會缺少wifi drive sudo apt-get install bcmwl-kernel-s ...

  2. gulp压缩css

    gulp压缩css,选用的依赖是gulp-clean-css,在压缩大型项目时还对用到一个dom流压缩文件选取的依赖gulp-dom-src 依赖安装:npm i gulp-clean-css 依赖安 ...

  3. HTTP超详细总结

    HTTP协议概述 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的 ...

  4. 极致CMS建站系统后台GETSHELL

    起因 正在学习代码审计 看到有人提交了一个注入https://www.cnvd.org.cn/flaw/show/CNVD-2019-42775 想试试看还有没有别的漏洞 受影响版本 v1.6.3 - ...

  5. 使用element-ui 组件动态合并table的行/列(第二次修改)

    这是第二次修改,在通过调用后台接口返回来的时候,发现了代码中的问题:现在将博客中错误的地方改过来,添加备注 文章需求:动态实现table表格中行/列的自动合并 使用框架及UI类库:Vue+Elemen ...

  6. 一,Jetty启动

    一,Jetty安装 从官网download.eclipse.org/jetty/ 下载需要的版本,在指定目录解压即可,下面用$JETTY_HOME表示Jetty的解压目录,也就是安装目录.我用的版本是 ...

  7. jumpserver3.0页面配置

    一.jumpserver的启动 1 2 Jumpserver的启动和重启 [root@test-vm001 install]# /opt/jumpserver/service.sh start/res ...

  8. 菩提圣心诀---zabbix自定义key监控oracle连接状态(python脚本)

    目的:此次实验目的是为了zabbix服务端能够实时监控某服务器上oracle实例能否正常连接 环境:1.zabbix_server 2.zabbix_agent(含有oracle) 主要知识点: 1. ...

  9. tire 树入门

    博客: 模板: 前缀是否出现: /* trie tree的储存方式:将字母储存在边上,边的节点连接与它相连的字母 trie[rt][x]=tot:rt是上个节点编号,x是字母,tot是下个节点编号 * ...

  10. 装完某些软件之后IE主页被https://www.hao123.com/?tn=93453552_hao_pg劫持

    今天重装电脑,装完某些软件之后发现IE主页被https://www.hao123.com/?tn=93453552_hao_pg劫持,然后百度各种解决方法都没用,甚至是修改注册表依然没啥用 最后忽然看 ...