zoukankan      html  css  js  c++  java
  • 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(" ");
          }
       }
       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(" ");
          }
       }
       return 0;
    }   

      





  • 相关阅读:
    联合索引和多个单列索引选择
    CentOS6.5 一台服务器同时安装多个Mysql数据库
    一次CentOS的服务器被攻击教训
    java版本的memcache静态化
    mysql存储空间满的处理方式
    MariaDB 10.0 和 MariaDB 10.1 存储过程中 PREPARE FROM EXECUTE 区别
    CentOS6.x 优化脚本
    Mysql 使用 “LOAD DATA INFILE”需要注意的问题
    Mysql 日期类型比较 TIMESTAMPDIFF
    CentOS6.x 源码安装Nginx
  • 原文地址:https://www.cnblogs.com/csnd/p/12063305.html
Copyright © 2011-2022 走看看