• hdu3338 / 方格横纵和问题终极版,最大流斩


    此题被誉为神奇最大流,诱惑我去做了下,感觉也是通常的思路。

    题意:1.用1-9去填,满足所给的行/列和要求(和那个什么游戏差不多。。。)

    求一种合法方案,输出。如:

                  

    一看,直接就建图了,每个点在白色的点中间,由横和=纵和,管理横和的在左边,纵和的点在右边。S->横和点,纵和点到t,建图即可。

    有一点注意,由于只能用1-9去填,是有上下界的网络流问题,所以这里有点比较巧妙,所有白色的点都减去1,和也对应减去几。用0做1,1做2...8做9.一一对应,实现转移为一般最大流问题。最后再加一即可。

    #include<iostream>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<string>
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int maxv=20100,maxe=1000101;
    int nume=0;int head[maxv];int e[maxe][3];
    void inline adde(int i,int j,int c)
    {
        e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
        e[nume++][2]=c;
        e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
        e[nume++][2]=0;
    }
    int ss,tt,n,m;
    int vis[maxv];int lev[maxv];
    bool bfs()
    {
        for(int i=0;i<maxv;i++)
          vis[i]=lev[i]=0;
        queue<int>q;
        q.push(ss);
        vis[ss]=1;
        while(!q.empty())
        {
            int cur=q.front();
            q.pop();
            for(int i=head[cur];i!=-1;i=e[i][1])
            {
                int v=e[i][0];
                if(!vis[v]&&e[i][2]>0)
                {
                    lev[v]=lev[cur]+1;
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
        return vis[tt];
    }
    int dfs(int u,int minf)
    {
        if(u==tt||minf==0)return minf;
        int sumf=0,f;
        for(int i=head[u];i!=-1&&minf;i=e[i][1])
        {
            int v=e[i][0];
            if(lev[v]==lev[u]+1&&e[i][2]>0)
            {
                f=dfs(v,minf<e[i][2]?minf:e[i][2]);
                e[i][2]-=f;e[i^1][2]+=f;
                sumf+=f;minf-=f;
            }
        }
        if(!sumf) lev[u]=-1;
        return sumf;
    }
    int dinic()
    {
        int sum=0;
        while(bfs())sum+=dfs(ss,inf);
        return sum;
    }
    struct cell         //方块
    {
         int clour;
         int x,y;
    };
    cell ces[102][102];
    void read_build()
    {
        string ts;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                cin>>ts;
                if(ts=="XXXXXXX")      //黑色
                  {
                      ces[i][j].clour=0;
                      ces[i][j].x=ces[i][j].y=-1;
                  }
                else if(ts==".......")   //白色
                {
                     ces[i][j].clour=5;
                     ces[i][j].x=ces[i][j].y=0;
                }
                else if(ts[0]=='X'&&ts[4]!='X')    //横向要填
                {
                     ces[i][j].clour=2;
                     ces[i][j].x=((ts[4]-'0')*10+(ts[5]-'0'))*10+(ts[6]-'0');
                     ces[i][j].y=-1;
                }
                 else if(ts[0]!='X'&&ts[4]=='X')   //纵向要填
                {
                     ces[i][j].clour=3;
                     ces[i][j].y=((ts[0]-'0')*10+(ts[1]-'0'))*10+(ts[2]-'0');
                     ces[i][j].x=-1;
                }
                else                          //都要
                {
                     ces[i][j].clour=4;
                     ces[i][j].y=((ts[0]-'0')*10+(ts[1]-'0'))*10+(ts[2]-'0');
                     ces[i][j].x=((ts[4]-'0')*10+(ts[5]-'0'))*10+(ts[6]-'0');
                }
            }
          for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
           {
               //cout<<ces[i][j].clour<<endl;
             //  cout<<i*m+j<<" ";
           }
    
    
        for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
          {
              int counts=0;
              if(ces[i][j].clour==2) //横向的
              {
                  for(int k=j+1;k<m;k++)
                  {
                      if(ces[i][k].clour!=5)break;
                      adde(i*m+j,i*m+k,8);
                      counts++;
                  }
                  adde(ss,i*m+j,ces[i][j].x-counts);
              }
              else if(ces[i][j].clour==3)   //纵向的
             {
                  for(int k=i+1;k<n;k++)
                  {
                     if(ces[k][j].clour!=5)break;
                      adde(k*m+j,i*m+j,8);
                      counts++;
                  }
                  adde(i*m+j,tt,ces[i][j].y-counts);
              }
               else if(ces[i][j].clour==4)    //都要填的,一个格子要2个编号,注意。
             {
    
                  for(int k=j+1;k<m;k++)
                  {
                     if(ces[i][k].clour!=5)break;
                      adde(i*m+j,i*m+k,8);
                      counts++;
                  }
                  adde(ss,i*m+j,ces[i][j].x-counts);
                counts=0;
                  for(int k=i+1;k<n;k++)
                  {
                       if(ces[k][j].clour!=5)break;
                      adde(k*m+j,i*m+j+n*m+2,8);
                      counts++;
                  }
                  adde(i*m+j+n*m+2,tt,ces[i][j].y-counts);
              }
          }
         // adde(0,ss,2);
       /* for(int i=0;i<=n*m+1;i++)
          for(int j=head[i];j!=-1;j=e[j][1])
          {
              printf("%d->%d:%d
    ",i,e[j][0],e[j][2]);
          }*/
    }
    void out()
    {
        for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
          {
              if(ces[i][j].clour!=5)printf("_");
              else
              {
                  int sflow=0;
                  for(int k=head[i*m+j];k!=-1;k=e[k][1])      //统计的时候只要正向边(这里注意!),其实每个点也就一条出的正向边
                  {
                      if(k%2==0)
                       sflow+=8-e[k][2];
                  }
                  printf("%d",sflow+1);
              }
              if(j==m-1)printf("
    ");
              else printf(" ");
          }
    }
    void init()
    {
        nume=0;
        memset(head,-1,sizeof(head));
        ss=n*m;tt=n*m+1;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            read_build();
            dinic();
            out();
        }
        return 0;
    }
    






  • 相关阅读:
    URL传递中文:Server.UrlEncode与Server.UrlDecode
    面向对象的封装性和多态性
    C#虚基类继承与接口的区别
    C# String与string的区别
    C# 索引器的使用
    ASP.NET 页面之间传递值的几种方式
    SQL Server中的游标CURSOR
    OpenLayers中的图层(转载)
    OpenLayers介绍和第一个例子(转载)
    SQL笔记-第七章,表连接
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925770.html
Copyright © 2020-2023  润新知