hdu 3338 最大流 ****
题意:

黑格子右上代表该行的和,左下代表该列下的和
链接:点我
这题可以用网络流做。以空白格为节点,假设流是从左流入,从上流出的,流入的容量为行和,流出来容量为列和,其余容量不变。求满足的最大流。由于流量有上下限限制,可以给每个数都减掉1,则填出来的数字范围为0—8, 就可以用单纯的网络流搞定了。求出来再加上就可以了。
这一题主要是在建图
建图:
一共有四类点:
1. 构造源点ST,汇点ED
2. 有行和的格子,即\上面有值的格子,此类节点设为A
3. 空白格,设为B
4. 有列和的格子,即\下面有值的格子,设为C
则可以建边:
1. ST------------A 容量:行和
2. A----------- B 容量:8
3. B------------C 容量:8
4. C------------ED 容量:列和
当然,反向边容量都置为0。
就是这么难~~
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std; #define INF 999999999
#define MAXN 14000
#define RE(x) (x)^1 int head[MAXN];
int map[][];
int st,ed;
struct Edge
{
int v,next;
int val;
Edge(){}
Edge( int V , int NEXT , int W = ):v(V),next(NEXT),val(W){}
}edge[]; struct gg
{
int x,y;
int val;
}row[MAXN],col[MAXN];
int emp,row_num,col_num;
int lvl[MAXN], gap[MAXN];
int cnt_edge;
int n,m,T;
int empty[MAXN]; void Insert_Edge( int u , int v , int flow = ) { edge[cnt_edge] = Edge(v,head[u],flow);
head[u] = cnt_edge++;
edge[cnt_edge] = Edge(u,head[v]);
head[v] = cnt_edge++; } void Init(){
cnt_edge = ;
memset(head,-,sizeof(head));
memset(lvl, , sizeof (lvl));
memset(gap, , sizeof (gap));
} int dfs(int u, int flow)
{
if (u==ed) {
return flow;
}
int tf = , sf, mlvl = ed-;
for (int i= head[u]; i != -; i = edge[i].next) {
if (edge[i].val > ) {
if (lvl[u] ==lvl[edge[i].v]+) {
sf = dfs(edge[i].v, min(flow-tf, edge[i].val));
edge[i].val -= sf;
edge[RE(i)].val += sf;
tf += sf;
if (lvl[st] >=ed) {
return tf;
}
if (tf == flow) {
break;
}
}
mlvl = min(mlvl, lvl[edge[i].v]);
}
}
if (tf == ) {
--gap[lvl[u]];
if (!gap[lvl[u]]) {
lvl[st] =ed;
}
else {
lvl[u] = mlvl+;
++gap[lvl[u]];
}
}
return tf;
} int sap()
{
int ans = ;
gap[]=ed;
while (lvl[st] <ed) {
ans += dfs(st, INF);
}
return ans;
} int print( int tp ) {
int ans = ;
int id = tp + row_num+;
for( int i = head[id] ; i != - ; i = edge[i].next ) {
int v = edge[i].v;
if( v <=row_num+ )
{
ans+= edge[i].val;
break;
}
}
return ans+;
} int main() { int i,j; char s[]; while(scanf("%d%d",&n,&m)!=-)
{
emp=row_num=col_num=;
for(i=;i<n;i++)
for(j=;j<m;j++)
{
scanf("%s",s);
if(s[]=='.')
{
map[i][j]=++emp;
}
else
{
map[i][j]=-;
if(s[]!='X')
{
int tp=(s[]-'')*+(s[]-'')*+s[]-'';
row[++row_num].x=i;
row[row_num].y=j;
row[row_num].val=tp; }
if(s[]!= 'X' ) {
int tp = (s[]-'')*+(s[]-'')*+s[]-'';
col[++col_num].x = i;
col[col_num].y = j;
col[col_num].val = tp;
} } }
T=emp+col_num+row_num+;
st=;
ed=T;
Init();
for(i=;i<=row_num;i++)
{
int pos = i;
int x = row[i].x;
int y = row[i].y;
int cnt_len = ;
for( y=y+; y <m ; y++ ) {
if( map[x][y] != - ) {
cnt_len++;
Insert_Edge(i+, row_num+ map[x][y]+,);
} else break;
}
Insert_Edge(st,pos+,row[i].val-cnt_len);
} for( i = ; i <=col_num ; i++ ) {
int pos =i++row_num+emp;
int x = col[i].x;
int y = col[i].y;
int cnt_len = ;
for( x=x+ ; x < n ; x++ ) {
if( map[x][y] != - ) {
cnt_len++;
Insert_Edge(row_num+ map[x][y]+,pos,); } else break;
}
Insert_Edge(pos,ed,col[i].val-cnt_len);
}
sap();
for(i=;i<n;i++)
{
for(j=;j<m;j++)
{ if(map[i][j]==-)
printf("_ ");
else
printf("%d ",print(map[i][j]));
}
printf("\n");
}
} return ;
}
2015/5/26
kuangbin大法:
/*
* HDU 3338 Kakuro Extension
* 题目意思就是在n*m的格子中,有黑白两种格子。要在白格子中填入数字1~9
* 每一段横竖连续的白格子的和是知道的。
* 求出一种满足的,保证有解。
* 最大流。
* 按照横竖段进行编号。然后行进列出,构造图形。
*
* 为了保证填入的数字是1~9,所以一开始每个格子减掉了1,相应的流入和流出都减掉。
* 然后格子的边的赋值为8.
* 还有就是要记录下相应边的编号,便于输出结果。
*
*/ #include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std; const int MAXN=;
const int MAXM=;
const int INF=0x3f3f3f3f;
struct Node
{
int to,next,cap;
}edge[MAXM];
int tol;
int head[MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol=;
memset(head,-,sizeof(head));
}
void addedge(int u,int v,int w,int rw=)
{
edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++;
}
int sap(int start,int end,int nodenum)
{
memset(dis,,sizeof(dis));
memset(gap,,sizeof(gap));
memcpy(cur,head,sizeof(head));
int u=pre[start]=start,maxflow=,aug=-;
gap[]=nodenum;
while(dis[start]<nodenum)
{
loop:
for(int &i=cur[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap&&dis[u]==dis[v]+)
{
if(aug==-||aug>edge[i].cap)
aug=edge[i].cap;
pre[v]=u;
u=v;
if(v==end)
{
maxflow+=aug;
for(u=pre[u];v!=start;v=u,u=pre[u])
{
edge[cur[u]].cap-=aug;
edge[cur[u]^].cap+=aug;
}
aug=-;
}
goto loop;
}
}
int mindis=nodenum;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap&&mindis>dis[v])
{
cur[u]=i;
mindis=dis[v];
}
}
if((--gap[dis[u]])==)break;
gap[dis[u]=mindis+]++;
u=pre[u];
}
return maxflow;
} char str[][][];
int lx[][];//存横条的标号
int ly[][];//存竖条的标号
int num[];//记录lx,ly数组中出现的次数,因为题目要求填入的数字是1~9,所以先全部变1,相应的流要减少
int id[][];//相应的边的编号,便于最后统计结果 int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m;
while(scanf("%d%d",&n,&m)==)
{
for(int i=;i<n;i++)
for(int j=;j<m;j++)
scanf("%s",str[i][j]);
init();
int tt=;//结点标号
memset(lx,,sizeof(lx));
memset(ly,,sizeof(ly));
memset(num,,sizeof(num));
for(int i=;i<n;i++)
for(int j=;j<m;j++)
{
if(strcmp(str[i][j],".......")!=)continue;
if(j== || lx[i][j-]==)lx[i][j]=++tt;
else lx[i][j]=lx[i][j-];
num[lx[i][j]]++;
}
for(int j=;j<m;j++)
for(int i=;i<n;i++)
{
if(strcmp(str[i][j],".......")!=)continue;
if(i== || ly[i-][j]==)ly[i][j]=++tt;
else ly[i][j]=ly[i-][j];
num[ly[i][j]]++;
}
int start=,end=tt+,nodenum=tt+;
for(int i=;i<n;i++)
for(int j=;j<m;j++)
if(strcmp(str[i][j],".......")==)
{
addedge(lx[i][j],ly[i][j],);
id[i][j]=tol-;//记录下来
}
for(int i=;i<n;i++)
for(int j=;j<m;j++)
{
if(str[i][j][]!='\\')continue;
if(str[i][j][]!='X')
{
int tmp=(str[i][j][]-'')*+(str[i][j][]-'')*+(str[i][j][]-'');
if(ly[i+][j]!=)
addedge(ly[i+][j],end,tmp-num[ly[i+][j]]);
}
if(str[i][j][]!='X')
{
int tmp=(str[i][j][]-'')*+(str[i][j][]-'')*+(str[i][j][]-'');
if(lx[i][j+]!=)
addedge(start,lx[i][j+],tmp-num[lx[i][j+]]);
}
}
sap(start,end,nodenum);
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(j>)printf(" ");
if(strcmp(str[i][j],".......")!=)printf("_");
else printf("%c",''+-edge[id[i][j]].cap);
}
printf("\n");
}
}
return ;
}
hdu 3338 最大流 ****的更多相关文章
- HDU 3338 Kakuro Extension (网络流,最大流)
HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...
- HDU 1532 最大流入门
1.HDU 1532 最大流入门,n个n条边,求第1点到第m点的最大流.只用EK做了一下. #include<bits/stdc++.h> using namespace std; #pr ...
- HDU - 3338 Kakuro Extension (最大流求解方格填数)
题意:给一个方格,每行每列都有对白色格子中的数之和的要求.每个格子中的数范围在[1,9]中.现在给出了这些要求,求满足条件的解. 分析:本题读入和建图比较恶心... 用网络流求解.建立源点S和汇点T, ...
- L - Kakuro Extension - HDU 3338 - (最大流)
题意:有一个填数字的游戏,需要你为白色的块内填一些值,不过不能随意填的,是有一些规则的(废话),在空白的上方和作方给出一些值,如果左下角有值说明下面列的和等于这个值,右上角的值等于这行后面的数的和,如 ...
- hdu 4289 最大流拆点
大致题意: 给出一个又n个点,m条边组成的无向图.给出两个点s,t.对于图中的每个点,去掉这个点都需要一定的花费.求至少多少花费才能使得s和t之间不连通. 大致思路: 最基础的拆点最大 ...
- Going Home HDU - 1533 费用流
http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...
- hdu 4975 最大流快版
http://acm.hdu.edu.cn/showproblem.php?pid=4975 给出每行每列的和,问是否存在这样的表格:每个小格放的数字只能是0--9. 直接用第八场最大流模板. #in ...
- hdu 4888 最大流慢板
http://acm.hdu.edu.cn/showproblem.php?pid=4888 添加一个源点与汇点,建图如下: 1. 源点 -> 每一行对应的点,流量限制为该行的和 2. 每一行对 ...
- hdu 2732 最大流 **
题意:题目是说一个n*m的迷宫中,有每个格子有柱子.柱子高度为0~3,高度为0的柱子是不能站的(高度为0就是没有柱子)在一些有柱子的格子上有一些蜥蜴,一次最多跳距离d,相邻格子的距离是1,只要跳出迷宫 ...
随机推荐
- vue引入jquery的方法
1.局部引入 通过命令下载jquery npm install jquery --save-dev 在需要引入jquery的组件中通过import $ from 'jquery'引入即可 2.全局 ...
- perl6: hash小笔记
> ,,, { => , => } > my $a = :%h h => { => , => } > $a.perl :h({, }) > my ...
- asp.net操作word 配置在IIS上出现的问题
异常: 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问. (异常来自 ...
- 十三、springboot集成定时任务(Scheduling Tasks)
定时任务(Scheduling Tasks) 在springboot创建定时任务比较简单,只需2步: 1.在程序的入口加上@EnableScheduling注解. 2.在定时方法上加@Schedule ...
- 微软Holographic将更名为Windows Mixed Reality
微软Holographic将更名为Windows Mixed Reality ----世界变化好快. 还没来得及细细品味,它就已经更名了. 程序员的焦虑,处在一个信息大爆炸的年代,大数据,云计算,机 ...
- asterisk各种报错
1.控制台打印出: Got SIP response "Temporarily Unavailable" back from 210.13.87.110:5060 造成原因:在 ...
- 20155225 实验三《敏捷开发与XP实践》实验报告
20155225 实验三<敏捷开发与XP实践>实验报告 一.使用工具(Code->Reformate Code)把代码重新格式化 IDEA里的Code菜单有很多实用的功能可以帮助我们 ...
- Elasticsearch 6.x 入门测试
首先听一下官方的话: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 我尝试了使用Java作为Cl ...
- Radon变换——MATLAB
算法说明: 图像的Radon变换是每个像素的Radon变换的总和. 该算法首先将图像中的像素分成四个子像素,并分别投影每个子像素,如下图所示. 根据投影位置和箱体中心之间的距离,每个子像素的贡献按比例 ...
- ElasticSearch实战概要
最近中美关系越来越紧张,国内经济下滑,股市一片惨淡,互联网行业越来越不景气,动不动都是跌掉几千亿市值,来写一些文档来抚慰这颗受伤的心吧... 随着互联网的发展,数据越来越重要,每个公司保存的数据也是越 ...