zoukankan      html  css  js  c++  java
  • hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

    题意:方格取数,如果取了相邻的数,那么要付出一定代价。(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪。。。)

        建图:  对于相邻问题,经典方法:奇偶建立二分图。对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权。

       ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理;若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) )。

      自己的确还没有理解其本质精妙所在。不知何以然也。(开始多敲多了几个else一直跪!)

    #include<iostream>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<set>
    #include<vector>
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int maxv=2550,maxe=20000;
    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,k;
    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;
    };
    int mapp[52][52];int must[maxv];int sums=0;
    void read_build()
    {
        for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
          {
            scanf("%d",&mapp[i][j]);
            sums+=mapp[i][j];
           }
         int aa,bb;
        for(int i=0;i<k;i++)
        {
            scanf("%d%d",&aa,&bb);
           must[(aa-1)*m+bb-1]=1;
        }
        for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
          {
             if((i+j)%2==0)
             {
                 if(must[i*m+j])
                  adde(ss,i*m+j,inf);
                 else
                  adde(ss,i*m+j,mapp[i][j]);
                 if(i-1>=0)
                     adde(i*m+j,(i-1)*m+j,2*(mapp[i][j]&mapp[i-1][j]));
                  if(i+1<n)
                    adde(i*m+j,(i+1)*m+j,2*(mapp[i][j]&mapp[i+1][j]));
                  if(j-1>=0)
                    adde(i*m+j,i*m+j-1,2*(mapp[i][j]&mapp[i][j-1]));
                  if(j+1<m)
                    adde(i*m+j,i*m+j+1,2*(mapp[i][j]&mapp[i][j+1]));
             }
             else
             {
                  if(must[i*m+j])
                  adde(i*m+j,tt,inf);
                 else
                  adde(i*m+j,tt,mapp[i][j]);
             }
          }
      /*  for(int i=0;i<=tt;i++)
          for(int j=head[i];j!=-1;j=e[j][1])
          {
              if(j%2==0)
              printf("%d->%d:%d
    ",i,e[j][0],e[j][2]);
          }*/
    }
    void init()
    {
        nume=0;sums=0;
        ss=n*m+2;tt=ss+1;
        for(int i=0;i<=tt;i++)
          {
              head[i]=-1;
              must[i]=0;
          }
    }
    int main()
    {
          while(scanf("%d%d%d",&n,&m,&k)!=EOF)
         {
             init();
            read_build();
           int ans;
           ans=sums-dinic();
          printf("%d
    ",ans);
        }
        return 0;
    }
    
    


     

  • 相关阅读:
    【数据结构】线性表&&顺序表详解和代码实例
    【智能算法】超详细的遗传算法(Genetic Algorithm)解析和TSP求解代码详解
    【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)
    【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解
    10. js时间格式转换
    2. 解决svn working copy locked问题
    1. easyui tree 初始化的两种方式
    10. js截取最后一个斜杠后面的字符串
    2. apache整合tomcat部署集群
    1. apache如何启动
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925697.html
Copyright © 2011-2022 走看看