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,只要跳出迷宫 ... 
随机推荐
- 【洛谷题解】P2303 [SDOi2012]Longge的问题
			题目传送门:链接. 能自己推出正确的式子的感觉真的很好! 题意简述: 求\(\sum_{i=1}^{n}gcd(i,n)\).\(n\leq 2^{32}\). 题解: 我们开始化简式子: \(\su ... 
- 利用Volatility对Linux内存取证分析-常用命令翻译
			命令翻译 linux_apihooks - 检查用户名apihooks linux_arp - 打印ARP表 linux_aslr_shift - 自动检测Linux aslr改变 linux_ban ... 
- ntpdate[35450]: the NTP socket is in use, exiting
			当前主机已是NTP服务器,需关闭当前NTP服务,再同步其他NTP服务器的时间 service ntpd stop 然后ps -ef | grep ntp看进程是否已杀掉 然后再次ntpdate Ser ... 
- mysql5.7半自动同步设置【转】
			mysql的主从复制主要有3种模式: a..主从同步复制:数据完整性好,但是性能消耗高 b.主从异步复制:性能消耗低,但是容易出现主从数据唯一性问题 c.主从半自动复制:介于上面两种之间.既能很好的保 ... 
- AngularJS中ng-class使用方法
			转自:https://blog.csdn.net/jumtre/article/details/50802136 其他博文ng-class使用方法:https://blog.csdn.net/sina ... 
- RestTemplate中文乱码问题(spring-web3.0.7版本)
			从网上找的方法: 方法一: //resttemplate乱码问题 //3.1.X以上版本使用 // restTemplate.getMessageConverters().add(0, StringH ... 
- 【Android开发日记】之入门篇(六)——Android四大组件之Broadcast Receiver
			广播接受者是作为系统的监听者存在着的,它可以监听系统或系统中其他应用发生的事件来做出响应.如设备开机时,应用要检查数据的变化状况,此时就可以通过广播来把消息通知给用户.又如网络状态改变时,电量变化时都 ... 
- Extjs6设置Store、Ajax、form的请求方式(GET、POST)
			Extjs6 设置Store.Ajax.form的请求方式(GET.POST) Ajax请求和Form的submit方法设置请求方式和原来一样,使用method : 'POST'设置 // 表单提交 ... 
- mac系统安装redis
			1.下载 打开官网:https://redis.io/ Download---Stable---Download3.2.8,下载最新稳定版,这里是3.2.8 2.安装 下载完成后,打开命令行工具,执行 ... 
- PL/SQL开发中动态SQL的使用方法
			一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DDL语句及系统控制语句,可以通过使 ... 
