hdu3338 最大流
题意:
给你一个N*M的网格,上面有的有一些数字,要求填充数字,满足的规则是这样:
答案不唯一,只要满足和的关系就可以,还有就是只能用1--9之间的数字填充,而且每一行或一列可以重复使用某个数字,观察每个要填充的点我们会发现,其实该点只于他所在的"行和"限制和所在的"列和"限制,我们可以把点分为三类,白色填充,左下半有数,右下半
有数 ,(其他的没用,不用管 ,左下和右上都有数的一定要拆成两个点),只要权衡好这三类点就ok了,那么我们可以直接添加 超级远点s ,超级汇点e ,左下进右上出(也可以反过来);题目要求是1--9 ,最大流可能会产生0所以直接0--8,输出的时候在+1就行.题意既然说是保证有解,那么最大流肯定会满流,最后每个点流多少就输出多少+1就ok;
建图:
(1)s 和所有左下有数的点连 ,流量是左下的数字减去他下面空白行的个数(因为是0--8每个都少了1 ,一共有多少个就少多少个)
(2)所有左下角有数的点和他下面的这一列的空白点相连,流量 8
(3)所有右上角有数的被他所在的这一列空白的连接,记住是被连接,(方向别反了),还有注意一点就是如果该点左下角有数了,那么一定要拆点,不然会冲突,流量是8;
(4)第三步中所有被连接的点在连接e,流量是该点右上角的数 - 这一行的空白格子个数.原因和(1) 一样.
建图后直接一遍最大流,然后根据流量情况就能输出答案了, 题目是 Special Judge ..所以随便跑一遍就行了,还有就是别用DINIC,会超时,就算我把点都离散化了依然超时,我用的是
SAP之前没用过,随便找了个模板改改用的. 当某个点有两个值时一定要拆点.同时可以离散化去优化.
下面是代码,第一个是TLE代码(DINIC),第二个是AC代码(SAP);
// 超时的DINIC
#include<stdio.h>
#include<string.h>
#include<queue>
#define N_node 100 * 100 * 2 + 100
#define N_edge 500000
#define N 100 + 5
#define inf 1000000000
using namespace std;
typedef struct
{
char node[8];
}NODE;
typedef struct
{
int to ,next ,cost;
}STAR;
typedef struct
{
int x ,dep;
}DEP;
NODE map[N][N];
STAR E[N_edge];
DEP xin ,tou;
int list[N_node] ,tot;
int list2[N_node] ,deep[N_node];
int X[N*N*2+100];
void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot;
E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
}
int minn(int x ,int y)
{
return x < y ? x : y;
}
bool BFS_DEEP(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s ,xin.dep = 0;
queue<DEP>q;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.dep = tou.dep + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.dep;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
list2[i] = list[i];
return deep[t] != -1;
}
int DFS_FLOW(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = list2[s] ;k ;k = E[k].next)
{
list2[s] = k;
int to = E[k].to;
int c = E[k].cost;
if(deep[to] != deep[s] + 1 || !c)
continue;
int temp = DFS_FLOW(to ,t ,minn(c ,flow - nowflow));
nowflow += temp;
E[k].cost -= temp;
E[k^1].cost += temp;
if(nowflow == flow) break;
}
if(!nowflow) deep[s] = 0;
return nowflow;
}
int DINIC(int s ,int t ,int n)
{
int ans = 0;
while(BFS_DEEP(s ,t ,n))
{
ans += DFS_FLOW(s ,t ,inf);
}
return ans;
}
int main ()
{
int i ,j ,n ,m ,s ,e;
while(~scanf("%d %d" ,&n ,&m))
{
int sum_n = 0;
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
{
scanf("%s" ,map[i][j].node);
if(map[i][j].node[0] == '.')
{
sum_n ++;
continue;
}
if(map[i][j].node[0] != 'X')
sum_n ++;
if(map[i][j].node[4] != 'X')
sum_n ++;
}
s = 0 ,e = sum_n + 1;
sum_n = 0;
memset(X ,255 ,sizeof(X));
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
{
if(map[i][j].node[3] == 'X' || map[i][j].node[0] == '.') continue;
char t_str[8];
for(int ii = 0 ;ii <= 7 ;ii ++)
t_str[ii] = map[i][j].node[ii];
int a ,b ,mk = 0;
if(X[(i-1)*m+j] == -1) X[(i-1)*m+j] = ++sum_n;
int now = X[(i-1)*m+j];
if(t_str[0] != 'X')
{
mk = 1;
int temp = (t_str[0]-48)*100+(t_str[1]-48)*10+(t_str[2]-48)*1;
for(int ii = i + 1 ;ii <= n ;ii ++)
{
if(map[ii][j].node[0] != '.')
break;
temp --;
if(X[(ii - 1) * m + j] == -1) X[(ii - 1) * m + j] = ++sum_n;
b = X[(ii - 1) * m + j];
add(now ,b ,8);
}
add(s ,now ,temp);
}
if(t_str[4] != 'X')
{
if(mk) now = ++sum_n;
int temp = (t_str[4]-48)*100+(t_str[5]-48)*10+(t_str[6]-48)*1;
for(int jj = j + 1 ;jj <= m ;jj ++)
{
if(map[i][jj].node[0] != '.')
break;
temp --;
if(X[(i - 1) * m + jj] == -1) X[(i - 1) * m + jj] = ++sum_n;
a = X[(i - 1) * m + jj];
add(a ,now ,8);
}
add(now ,e ,temp);
}
}
DINIC(s ,e ,sum_n + 1);
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
{
if(j != 1) printf(" ");
if(map[i][j].node[0] != '.')
printf("_");
else
{
int k = list[X[(i - 1) * m + j]];
int c = E[k].cost;
printf("%d" ,8 - c + 1);
}
if(j == m) printf("\n");
}
}
return 0;
}
//SAP ac
#include<stdio.h>
#include<string.h>
#include<queue>
#define N 100 + 5
using namespace std;
typedef struct
{
char node[8];
}NODE;
NODE map[N][N];
int X[50000];
//***********************************************
const int MAXN=50000;//点数的最大值
const int MAXM=1000000;//边数的最大值
const int INF=0x3f3f3f3f;
struct Node
{
int from,to,next;
int cap;
}edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y
int nn;//n是总的点的个数,包括源点和汇点
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
edge[tol].from=u;
edge[tol].to=v;
edge[tol].cap=w;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].from=v;
edge[tol].to=u;
edge[tol].cap=0;
edge[tol].next=head[v];
head[v]=tol++;
}
void BFS(int start,int end)
{
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
gap[0]=1;
int que[MAXN];
int front,rear;
front=rear=0;
dep[end]=0;
que[rear++]=end;
while(front!=rear)
{
int u=que[front++];
if(front==MAXN)front=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(dep[v]!=-1)continue;
que[rear++]=v;
if(rear==MAXN)rear=0;
dep[v]=dep[u]+1;
++gap[dep[v]];
}
}
}
int SAP(int start,int end)
{
int res=0;
BFS(start,end);
int cur[MAXN];
int S[MAXN];
int top=0;
memcpy(cur,head,sizeof(head));
int u=start;
int i;
while(dep[start]<nn)
{
if(u==end)
{
int temp=INF;
int inser;
for(i=0;i<top;i++)
if(temp>edge[S[i]].cap)
{
temp=edge[S[i]].cap;
inser=i;
}
for(i=0;i<top;i++)
{
edge[S[i]].cap-=temp;
edge[S[i]^1].cap+=temp;
}
res+=temp;
top=inser;
u=edge[S[top]].from;
}
if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路
break;
for(i=cur[u];i!=-1;i=edge[i].next)
if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
break;
if(i!=-1)
{
cur[u]=i;
S[top++]=i;
u=edge[i].to;
}
else
{
int min=nn;
for(i=head[u];i!=-1;i=edge[i].next)
{
if(edge[i].cap==0)continue;
if(min>dep[edge[i].to])
{
min=dep[edge[i].to];
cur[u]=i;
}
}
--gap[dep[u]];
dep[u]=min+1;
++gap[dep[u]];
if(u!=start)u=edge[S[--top]].from;
}
}
return res;
}
//**************************************
int main ()
{
int i ,j ,n ,m ,s ,e;
while(~scanf("%d %d" ,&n ,&m))
{
int sum_n = 0;
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
{
scanf("%s" ,map[i][j].node);
if(map[i][j].node[0] == '.')
{
sum_n ++;
continue;
}
if(map[i][j].node[0] != 'X')
sum_n ++;
if(map[i][j].node[4] != 'X')
sum_n ++;
}
s = 0 ,e = sum_n + 1;
sum_n = 0;
memset(X ,255 ,sizeof(X));
memset(head ,255 ,sizeof(head));
tol = 0;
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
{
if(map[i][j].node[3] == 'X' || map[i][j].node[0] == '.') continue;
char t_str[8];
for(int ii = 0 ;ii <= 7 ;ii ++)
t_str[ii] = map[i][j].node[ii];
int a ,b ,mk = 0;
if(X[(i-1)*m+j] == -1) X[(i-1)*m+j] = ++sum_n;
int now = X[(i-1)*m+j];
if(t_str[0] != 'X')
{
mk = 1;
int temp = (t_str[0]-48)*100+(t_str[1]-48)*10+(t_str[2]-48)*1;
for(int ii = i + 1 ;ii <= n ;ii ++)
{
if(map[ii][j].node[0] != '.')
break;
temp --;
if(X[(ii - 1) * m + j] == -1) X[(ii - 1) * m + j] = ++sum_n;
b = X[(ii - 1) * m + j];
addedge(now ,b ,8);
}
addedge(s ,now ,temp);
}
if(t_str[4] != 'X')
{
if(mk) now = ++sum_n;
int temp = (t_str[4]-48)*100+(t_str[5]-48)*10+(t_str[6]-48)*1;
for(int jj = j + 1 ;jj <= m ;jj ++)
{
if(map[i][jj].node[0] != '.')
break;
temp --;
if(X[(i - 1) * m + jj] == -1) X[(i - 1) * m + jj] = ++sum_n;
a = X[(i - 1) * m + jj];
addedge(a ,now ,8);
}
addedge(now ,e ,temp);
}
}
nn = sum_n + 1 + 1;
SAP(s ,e);
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
{
if(j != 1) printf(" ");
if(map[i][j].node[0] != '.')
printf("_");
else
{
int k = head[X[(i - 1) * m + j]];
int c = edge[k].cap;
printf("%d" ,8 - c + 1);
}
if(j == m) printf("\n");
}
}
return 0;
}
hdu3338 最大流的更多相关文章
- HDU3338 Kakuro Extension —— 最大流、方格填数类似数独
题目链接:https://vjudge.net/problem/HDU-3338 Kakuro Extension Time Limit: 2000/1000 MS (Java/Others) ...
- hdu3338 Kakuro Extension 最大流
If you solved problem like this, forget it.Because you need to use a completely different algorithm ...
- HDU3338:Kakuro Extension(最大流)
Kakuro Extension Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu3338 / 方格横纵和问题终极版,最大流斩
此题被誉为神奇最大流,诱惑我去做了下,感觉也是通常的思路. 题意:1.用1-9去填,满足所给的行/列和要求(和那个什么游戏差不多...) 求一种合法方案,输出.如: 一看,直接就建图了,每个点在白 ...
- HDU3338 Kakuro Extension(最大流+思维构图)
这道题一定要写一下,卡了好久. 题意: 有黑白两种方格,最上边一行和最左边一列一定是黑色,然后其余的地方有可能是黑色,有可能是白色,和白色相邻的黑色方格里有数字(1个或2个), 现在要求在白色方格里填 ...
- 【最大流】【HDU3338】【Kakuro Extension】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3338 题目大意:填数字,使白色区域的值得和等于有值得黑色区域的相对应的值,用网络流来做 题目思路:增加 ...
- HDU 3338 Kakuro Extension (网络流,最大流)
HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...
- Kakuro Extension【最大流】
HDU-3338 这道题真的处理起来好复杂啊,题意就是个简单的方格填数问题,但是每个白点至少放1,那么最后的可能解是怎样的呢?我们是不是要把x轴上的和y轴上的统一起来,然后就是每个点都被对应的x和y匹 ...
- hdu4888 最大流(构造矩阵)
题意: 让你构造一个矩阵,满足每一行的和,和每一列的和都等于他给的,还要判断答案是否唯一,还有一点就是矩阵内所有的数字都是[0,k]范围的. 思路: 这个题目看完就让我想起了h ...
随机推荐
- CentOS 7关闭firewalld启用iptables 开放端口
在CentOS7中,有很多CentOS 6中的常用服务发生了变化. 其中iptables是其中比较大的一个.防火墙iptables被firewalld取代. 本文将介绍,如果采用systemctl关闭 ...
- 2020年12月-第02阶段-前端基础-CSS Day03
CSS Day03 盒子模型(CSS重点) css学习三大重点: css 盒子模型 . 浮动 . 定位 主题思路: 理解: 1.能说出盒子模型有那四部分组成 2.能说出内边距的作用以及对盒子的影响 3 ...
- RPC基础以及造一个RPC的轮子需要注意些什么
RPC基础以及造一个RPC的轮子需要注意些什么 前言 rpc即远程过程调用,是分布式系统常用的通信方法.远程可以是在一台机器上的不同进程或在不同一个机器上的不同进程.rpc更看重速度,像调用本地方法一 ...
- 在windows10中启动VmWare时,只要一启动虚拟机,电脑就会蓝屏死机(终止代码:SYSTEM_SERVICE_EXCEPTION)
在windows10中启动VmWare时,只要一启动虚拟机,电脑就会蓝屏死机(终止代码:SYSTEM_SERVICE_EXCEPTION) 没错就是这个,绿色的死亡按钮 原因: 第一种:windows ...
- Andrew BP 神经网络详细推导
Lec 4 BP神经网络详细推导 本篇博客主要记录一下Coursera上Andrew机器学习BP神经网络的前向传播算法和反向传播算法的具体过程及其详细推导.方便后面手撸一个BP神经网络. 目录 Lec ...
- 【Azure 服务总线】详解Azure Service Bus SDK中接收消息时设置的maxConcurrentCalls,prefetchCount参数
(Azure Service Bus服务总线的两大类消息处理方式: 队列Queue和主题Topic) 问题描述 使用Service Bus作为企业消息代理,当有大量的数据堆积再Queue或Topic中 ...
- 生成元(JAVA语言)
package 第三章; import java.util.Scanner; public class 生成元 { public static void main(String[] args) { / ...
- LuckyStar hctf2018
LuckyStar hctf2018 程序注册有TLS回调函数 char __stdcall TlsCallback_0(int a1, int a2, int a3) { char result; ...
- java例题_18 乒乓球比赛(对手问题)
1 /*18 [程序 18 乒乓球赛] 2 题目:两个乒乓球队进行比赛,各出三人.甲队为 a,b,c 三人,乙队为 x,y,z 三人.已抽签决定比赛名单. 3 有人向队员打听比赛的名单.a说他不和 x ...
- 20182217_刘洪宇 后门原理与实践 EXP2
1.后门概念 后门就是不经过正常认证流程而访问系统的通道. 哪里有后门呢? 编译器留后门 操作系统留后门 最常见的当然还是应用程序中留后门 还有就是潜伏于操作系统中或伪装为特定应用的专用后门程序. - ...