传送门

有上下界最小费用可行流,行列建边变形。

行列建边相信大家都做过,没做过的可以看一下这个题:bzoj3698XWW的难题,对应的我写的题解题解

这个题需要变形一下,不只是单纯的对行列进行连边,首先对于一个空格,我们知道它最多影响2个线索:1个横向的和1个纵向的

所以我们可以对于每个线索划分出一个块,这个块包含所有的能影响它的空格以及它自己,显然这个做法和行列连边是同性质的,正确性亦显然

所以我们就得出了一个位置最多属于两个块,这个时候如果不考虑修改已经可以判断当前局面是否可行了

但是需要考虑修改,发现一个位置修改后的权值范围是\([1,+\infty]\),上下界预定了。

对于第\(i\)行第\(j\)列的这个点来说,如果它不是既不是空格也不是线索。

假设它纵向属于第x块,横向属于第y块(假如x为0就将x改为源点,y为0就将y改为汇点,自己思考,很显然的)

以下的连边都是以这样的格式\(add(x,y,down,up,cost)\)(x连y,下界,上界,费用)

第一种情况:这是一个空格

显然需要先建出\(add(x,y,val,val,0)\)

假如这个点可以修改,建出\(add(x,y,0.inf,cost),add(y,x,0,val-1,cost)\)

这两条边是分别代表增加权值和减少权值,看不懂自己思考,很显然的

第二种情况:这个位置有左下角的线索(有右上角也没关系)

先建出\(add(s,x,val,val,0)\)

假如这个点可以修改,建出\(add(s,x,0.inf,cost),add(x,s,0,val-1,cost)\)

边的含义同第一种情况

第三种情况:这个位置有右上角的线索(有左下角也没关系)

先建出\(add(y,t,val,val,0)\)

假如这个点可以修改,建出\(add(y,t,0.inf,cost),add(t,y,0,val-1,cost)\)

边的含义同前两种情况


P.S:

1、上下界网络流的细节我就不赘言了,来写的肯定都会吧

2、本人阐述能力有点差,不懂只能看代码了

3、本人代码费用流部分写的zkw费用流,其他费用流算法也是可以的

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x) {
char ch; bool ok;
for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define ll long long
#define rg register
const int maxn=1e5+10;const ll inf=1e18;
int s,t,ss,tt,n,cnt=1,m,id,in[maxn],mp[31][31],val[70][70][3],va[70][70],vb[70][70];
int pre[maxn*2],nxt[maxn*2],h[maxn],w[maxn*2];
int cost[70][70][3];ll sum,ans,flow,v[maxn*2],tot,dis[maxn],sla[maxn];
bool vis[maxn];
void add(int x,int y,ll z,int d)
{
if(!z)return ;
pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z,w[cnt]=d;
pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=0,w[cnt]=-d;
}
ll dfs(int x,ll flow)
{
if(x==tt||!flow){ans+=dis[tt]*flow,tot+=flow;return flow;}
ll f=flow;vis[x]=1;
for(rg int i=h[x];i;i=nxt[i])
if(!vis[pre[i]]&&v[i])
{
if(dis[x]+w[i]==dis[pre[i]])
{
ll y=dfs(pre[i],min(f,v[i]));
f-=y,v[i]-=y,v[i^1]+=y;
if(!f)return flow;
}
else sla[pre[i]]=min(sla[pre[i]],dis[x]+w[i]-dis[pre[i]]);
}
return flow-f;
}
bool aug()
{
ll mx=inf;
for(rg int i=s;i<=tt;i++)if(!vis[i])mx=min(mx,sla[i]),sla[i]=inf;
if(mx==inf)return 1;
for(rg int i=s;i<=tt;i++)if(!vis[i])dis[i]+=mx;
return 0;
}
int main()
{
read(n),read(m);
for(rg int i=1;i<=n;i++)for(rg int j=1;j<=m;j++)read(mp[i][j]);
for(rg int i=1;i<=n;i++)
for(rg int j=1;j<=m;j++)
{
if(mp[i][j]==1)read(val[i][j][0]);
if(mp[i][j]==2)read(val[i][j][1]);
if(mp[i][j]==3)read(val[i][j][0]),read(val[i][j][1]);
if(mp[i][j]==4)read(val[i][j][2]);
if(mp[i][j]==1||mp[i][j]==3)
{
int now=++id,k=i;va[i][j]=now;k++;
while(mp[k][j]==4)va[k][j]=now,k++;
}
if(mp[i][j]==2||mp[i][j]==3)
{
int now=++id,k=j;vb[i][j]=now;k++;
while(mp[i][k]==4)vb[i][k]=now,k++;
}
}
s=0,t=++id;add(t,s,inf,0);ss=++id,tt=++id;
for(rg int i=1;i<=n;i++)
for(rg int j=1;j<=m;j++)
{
if(!mp[i][j])continue;
if(mp[i][j]==1)read(cost[i][j][0]);
if(mp[i][j]==2)read(cost[i][j][1]);
if(mp[i][j]==3)read(cost[i][j][0]),read(cost[i][j][1]);
if(mp[i][j]==4)read(cost[i][j][2]);
int x=va[i][j]?va[i][j]:s,y=vb[i][j]?vb[i][j]:t;
if(mp[i][j]==4)
{
add(x,y,0,0),in[x]-=val[i][j][2],in[y]+=val[i][j][2];
if(cost[i][j][2]!=-1)
add(x,y,inf,cost[i][j][2]),add(y,x,val[i][j][2]-1,cost[i][j][2]);
}
if(mp[i][j]==1||mp[i][j]==3)
{
add(s,x,0,0),in[s]-=val[i][j][0],in[x]+=val[i][j][0];
if(cost[i][j][0]!=-1)
add(s,x,inf,cost[i][j][0]),add(x,s,val[i][j][0]-1,cost[i][j][0]);
}
if(mp[i][j]==2||mp[i][j]==3)
{
add(y,t,0,0),in[y]-=val[i][j][1],in[t]+=val[i][j][1];
if(cost[i][j][1]!=-1)
add(y,t,inf,cost[i][j][1]),add(t,y,val[i][j][1]-1,cost[i][j][1]);
}
}
for(rg int i=s;i<=tt;i++)
{
if(in[i]>0)sum+=in[i],add(ss,i,in[i],0);
if(in[i]<0)add(i,tt,-in[i],0);
}
memset(sla,127,sizeof sla);
while(1)
{
while(1){memset(vis,0,sizeof vis);if(!dfs(ss,inf))break;}
if(aug())break;
}
printf("%lld\n",tot==sum?ans:-1);
}

bzoj5148:[BeiJing2018]Kakuro的更多相关文章

  1. HDU 3338 Kakuro Extension (网络流,最大流)

    HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...

  2. hdu3338 Kakuro Extension 最大流

    If you solved problem like this, forget it.Because you need to use a completely different algorithm ...

  3. HDU3338:Kakuro Extension(最大流)

    Kakuro Extension Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. HDU3338 Kakuro Extension —— 最大流、方格填数类似数独

    题目链接:https://vjudge.net/problem/HDU-3338 Kakuro Extension Time Limit: 2000/1000 MS (Java/Others)     ...

  5. 使用GAC加速 解决CSP问题 Kakuro - Cross Sums

    Kakuro - Cross Sums 问题如下 一个简单的例子 可以看出限制条件是某行或某列的某几个空白格子求和等于某个值,且每一个限制中的格子所填的数必须为1-9且互异. 直接暴力搜索,空白格子太 ...

  6. Kakuro Extension HDU - 3338 (Dinic)

    Kakuro puzzle is played on a grid of "black" and "white" cells. Apart from the t ...

  7. [BJWC2018] Kakuro

    一.题目 点此看题 二.解法 我一开始一直想不出来,直接刚这个题实在是太复杂了,因为一开始就是不合法的. 下次遇到复杂的题一定要想 调整法 ,我再不往这个方向想我吔屎 好了言归正传,我们先找一组可行的 ...

  8. L - Kakuro Extension - HDU 3338 - (最大流)

    题意:有一个填数字的游戏,需要你为白色的块内填一些值,不过不能随意填的,是有一些规则的(废话),在空白的上方和作方给出一些值,如果左下角有值说明下面列的和等于这个值,右上角的值等于这行后面的数的和,如 ...

  9. 【最大流】【HDU3338】【Kakuro Extension】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3338 题目大意:填数字,使白色区域的值得和等于有值得黑色区域的相对应的值,用网络流来做 题目思路:增加 ...

随机推荐

  1. Android笔记之Snackbar的基本使用

    使用Snackbar之前,须导入com.android.support:design 使用示例 package com.bu_ish.snackbar_test; import android.gra ...

  2. 阿里Java开发手册学习 2 异常日志

    异常日志 异常处理 1.不要捕获继承自RuntimeException的运行时异常类,这类异常通常由程序员来校验,来保证查询的健壮性. 2. 不要对大段代码 try catch,分清稳定代码和非稳定代 ...

  3. iOS 设备获取唯一标识符汇总

    在2013年3月21日苹果已经通知开发者,从2013年5月1日起,访问UIDID的应用将不再能通过审核,替代的方案是开发者应该使用“在iOS 6中介绍的Vendor或Advertising标示符”. ...

  4. 原来 Set 集合也可以排序

    Java 集合类主要由两个接口派生而出: Collection 和 Map.在 Collection 集合中,我们经常用到的是 List 集合和 Map 集合,而 Set 集合出场的机会就相对比较的少 ...

  5. Mall电商项目总结(一)——项目概述

    项目概述 此电商项目为本人学习项目,后端 使用nginx实现负载均衡转发请求到多台tomcat服务器,使用多台 redis服务器分布式 缓存用户登录信息. 项目已经部署到阿里云服务器,从阿里云linu ...

  6. HDU4850 Wow! Such String! —— 字符串构造

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4850 代码如下: #include <iostream> #include <cst ...

  7. Discuz/X3.1去掉标题中的Powered by Discuz!以及解决首页标题后的"-"

    虽然不提倡大家去掉版权信息,但是在实际操作的时候还是去掉,毕竟每个页面标题最后面出现”Powered by Discuz!“会显得页面标题比较冗长. 经过本人的实践,论坛里也有操作方法,不过那个操作方 ...

  8. JavaWeb学习总结(三)response与request

    一.response response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse.在客户端发出每个请求时,服务器 ...

  9. 【Codeforces】879D. Teams Formation 思维+模拟

    题意 给定$n$个数,重复拼接$m$次,相邻$k$个重复的可消除,问最后序列中有多少个数 首先可以发现当$k>=n$时,如果要使$n$个数可以被消除,那么$n$个数必须一样,否则$n$个数不能被 ...

  10. 24.如何结束返回值是void的方法

    如何结束返回值是void的方法? return;只能够出现在方法类型是void 的方法中,用来结束方法. return后面还可以跟数据,后面的数据可以是整数.字符串.false.ture.小数.主要看 ...