题意: 

           给你一个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 最大流的更多相关文章

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

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

  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 / 方格横纵和问题终极版,最大流斩

    此题被誉为神奇最大流,诱惑我去做了下,感觉也是通常的思路. 题意:1.用1-9去填,满足所给的行/列和要求(和那个什么游戏差不多...) 求一种合法方案,输出.如:   一看,直接就建图了,每个点在白 ...

  5. HDU3338 Kakuro Extension(最大流+思维构图)

    这道题一定要写一下,卡了好久. 题意: 有黑白两种方格,最上边一行和最左边一列一定是黑色,然后其余的地方有可能是黑色,有可能是白色,和白色相邻的黑色方格里有数字(1个或2个), 现在要求在白色方格里填 ...

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

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

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

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

  8. Kakuro Extension【最大流】

    HDU-3338 这道题真的处理起来好复杂啊,题意就是个简单的方格填数问题,但是每个白点至少放1,那么最后的可能解是怎样的呢?我们是不是要把x轴上的和y轴上的统一起来,然后就是每个点都被对应的x和y匹 ...

  9. hdu4888 最大流(构造矩阵)

    题意:       让你构造一个矩阵,满足每一行的和,和每一列的和都等于他给的,还要判断答案是否唯一,还有一点就是矩阵内所有的数字都是[0,k]范围的. 思路:       这个题目看完就让我想起了h ...

随机推荐

  1. Mybatis(一):手写一套持久层框架

    作者 : 潘潘 未来半年,有幸与导师们一起学习交流,趁这个机会,把所学所感记录下来. 「封面图」 自毕业以后,自己先创业后上班,浮沉了近8年,内心着实焦躁,虽一直是走科班路线,但在技术道路上却始终没静 ...

  2. OSI协议简述版

    OSI简介 OSI只是计算机网络中的一种协议名称缩写,它只是电脑间传输数据的协议,并不代表具体的物理设备,并且这种协议,只是被人为的划分为五层:物理层.数据链路层.网络层.传输层.应用层.记住,它只是 ...

  3. Linux速通05 文件处理与编辑

    使用 cat 命令进行文件的纵向合并 # 例:使用 cat 命令将 baby.age.baby.weight.baby.sex 这三个文件纵向合并为 baby文件 * cat baby.age bab ...

  4. Kibana 插件环境搭建教程

    原文 环境背景, Kibana 7.4.0, Elasticsearch 7.4.0 注意, 执行以下命令时, 尽量在管理员权限的命令行窗口里执行, 避免一些没有权限的报错; 1. 准备 Kibana ...

  5. FreeBSD 的xfce 终端动态标题不显示问题解决了:

    tcsh配置,home目录创建.tcshrc, 写入以下配置 alias h history 25 alias j jobs -l alias la ls -aF alias lf ls -FA al ...

  6. 有必要了解的大数据知识(一) Hadoop

    前言 之前工作中,有接触到大数据的需求,虽然当时我们体系有专门的大数据部门,但是由于当时我们中台重构,整个体系的开发量巨大,共用一个大数据部门,人手已经忙不过来,没法办,为了赶时间,我自己负责的系统的 ...

  7. 竖式问题(JAVA语言)

    package 第三章; import java.util.Scanner; public class 竖式问题 { public static void main(String[] args) { ...

  8. ubuntu修改默认启动内核

    一.序言 新换的笔记本由于太新的主板芯片,驱动还没有完善.每次升级系统内核都要小心谨慎.经常发生部分硬件驱动失败的事情.系统Ubuntu 20.04.2 LTS x86_64 ,我现在使用的两个版本的 ...

  9. 第15 章 : 深入解析 Linux 容器

    深入解析 Linux 容器 今天的内容主要分成以下三个部分 资源隔离和限制: 容器镜像的构成: 容器引擎的构成: 前两个部分就是资源隔离和限制还有容器镜像的构成,第三部分会以一个业界比较成熟的容器引擎 ...

  10. [Fundamental of Power Electronics]-PART II-8. 变换器传递函数-8.1 Bode图回顾

    8.0 序 工程设计过程主要包括以下几个过程: 1.定义规格与其他设计目标 2.提出一个电路.这是一个创造性的过程,需要利用工程师的实际见识和经验. 3.对电路进行建模.变换器的功率级建模方法已经在第 ...