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,只要跳出迷宫 ...
随机推荐
- Oracle环境变量与中文显示的问题
在CentOS(linux)下安装Oracle,对环境变量的设置有一些讲究. 一般我们可以把环境变量设置在/etc/profile文件中: # Oracle SettingsTMP=/tmp; exp ...
- 读sru代码
1. def read_corpus(path, eos="</s>"): data = [ ] with open(path) as fin: for line in ...
- Oracle Certified Java Programmer 经典题目分析(一)
Given: 1. public class returnIt { 2. returnType methodA(byte x, double y){ 3. return (short) x/y * 2 ...
- ARC073E Ball Coloring
Problem AtCoder Solution 把点映射至二维平面,问题就变成了给定 \(n\) 个点,可以把点对 \(y=x\) 对称,求覆盖所有点的最小矩形面积. 可以先把所有点放到 \(y=x ...
- poj1102
模拟 #include <iostream> #include <string> using namespace std; ][][] = { { ' ', '-', ' ', ...
- Flask:使用Eclipse+PyDev插件编辑基于package的项目
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2,Eclipse Oxygen.1a Release (4.7.1a),PyDev 6.3.2 本文记录了 使用Ecli ...
- 【前端vue开发】Hbuilder配置Avalon、AngularJS、Vue指令提示
偶尔也会研究一下前端内容,因为Hbuilder是基于eclipse开发的,所以用起来倍感亲切啊,而且在我尝试使用的几款前端开发工具中,Hbuilder的表现也是相当出色地,可以访问Huilder官网下 ...
- SQL Server操作实例
创建数据库 create database accountInfo/*创建账户信息数据库*/ 创建数据表 /*定义主码.外码.和人数.余额的取值范围.*/ /*创建储蓄所表*/ create tabl ...
- python学习day4软件目录结构规范
为什么要设计好目录结构? 参考:http://www.cnblogs.com/alex3714/articles/5765046.html "设计项目目录结构",就和"代 ...
- ajax传递的参数服务器端接受不到的原因
最常见的就是组织的json数据格式有问题,尝试把单引号改为双引号试试,如下: $datares = {"uname":$uname.val(),"phone": ...