zoukankan      html  css  js  c++  java
  • HDU 3820 Golden Eggs

    http://acm.hdu.edu.cn/showproblem.php?pid=3820

    题意:
    n*m的格子,每个格子放金蛋或银蛋,每个格子的金蛋和银蛋都有一个对应的点权,如果有两个金蛋相连,则需要G的代价,如果有两个银蛋相连,需要S的代价。

    思路:

    这道题和HDU的格子取数是一个套路。

    在前面的格子取数问题中,我们奇偶建图,相邻点之间连INF就代表这两个点中至少会选择一个,由于是最小割,肯定是选择权值小的点。这道题目的建图稍微复杂点,因为每个格子有三种选择,即可以选择放金蛋或是放银蛋或空着。首先,我们还是要奇偶建图,把一方的金蛋与源点相连,银蛋与汇点相连,而另一方的金蛋与汇点相连,银蛋与源点相连。每一方的金蛋与自己的银蛋相连,容量为INF,说明要么放金蛋,要么放银蛋。而相邻的蛋颜色相同时则边的容量为代价。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<queue>
      7 using namespace std;
      8 
      9 const int maxn = 1e5 + 5;
     10 const int INF=0x3f3f3f3f;
     11 
     12 struct Edge
     13 {
     14     int from,to,cap,flow;
     15     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     16 };
     17 
     18 struct Dinic
     19 {
     20     int n,m,s,t;
     21     vector<Edge> edges;
     22     vector<int> G[maxn];
     23     bool vis[maxn];
     24     int cur[maxn];
     25     int d[maxn];
     26 
     27     void init(int n)
     28     {
     29         this->n=n;
     30         for(int i=0;i<n;++i) G[i].clear();
     31         edges.clear();
     32     }
     33 
     34     void AddEdge(int from,int to,int cap)
     35     {
     36         edges.push_back( Edge(from,to,cap,0) );
     37         edges.push_back( Edge(to,from,0,0) );
     38         m=edges.size();
     39         G[from].push_back(m-2);
     40         G[to].push_back(m-1);
     41     }
     42 
     43     bool BFS()
     44     {
     45         queue<int> Q;
     46         memset(vis,0,sizeof(vis));
     47         vis[s]=true;
     48         d[s]=0;
     49         Q.push(s);
     50         while(!Q.empty())
     51         {
     52             int x=Q.front(); Q.pop();
     53             for(int i=0;i<G[x].size();++i)
     54             {
     55                 Edge& e=edges[G[x][i]];
     56                 if(!vis[e.to] && e.cap>e.flow)
     57                 {
     58                     vis[e.to]=true;
     59                     d[e.to]=d[x]+1;
     60                     Q.push(e.to);
     61                 }
     62             }
     63         }
     64         return vis[t];
     65     }
     66 
     67     int DFS(int x,int a)
     68     {
     69         if(x==t || a==0) return a;
     70         int flow=0, f;
     71         for(int &i=cur[x];i<G[x].size();++i)
     72         {
     73             Edge &e=edges[G[x][i]];
     74             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     75             {
     76                 e.flow +=f;
     77                 edges[G[x][i]^1].flow -=f;
     78                 flow +=f;
     79                 a -=f;
     80                 if(a==0) break;
     81             }
     82         }
     83         return flow;
     84     }
     85 
     86     int Maxflow(int s,int t)
     87     {
     88         this->s=s; this->t=t;
     89         int flow=0;
     90         while(BFS())
     91         {
     92             memset(cur,0,sizeof(cur));
     93             flow +=DFS(s,INF);
     94         }
     95         return flow;
     96     }
     97 }DC;
     98 
     99 int n,m;
    100 int G,S;
    101 int map[105][55];
    102 int dx[]={0,0,1,-1};
    103 int dy[]={1,-1,0,0};
    104 
    105 int main()
    106 {
    107     //freopen("D:\input.txt","r",stdin);
    108     int kase=0;
    109     int T;
    110     scanf("%d",&T);
    111     while(T--)
    112     {
    113         int sum=0;
    114         scanf("%d%d%d%d",&n,&m,&G,&S);
    115         int src=0,dst=2*n*m+1;
    116         DC.init(dst+1);
    117         for(int i=1;i<=n;i++)
    118         for(int j=1;j<=m;j++)
    119         {
    120             scanf("%d",&map[i][j]);
    121             sum+=map[i][j];
    122         }
    123         for(int i=1;i<=n;i++)
    124         for(int j=1;j<=m;j++)
    125         {
    126             scanf("%d",&map[i+n][j]);
    127             sum+=map[i+n][j];
    128         }
    129         for(int i=1;i<=n;i++)
    130         for(int j=1;j<=m;j++)
    131         {
    132             int id1=(i-1)*m+j;
    133             int id2=(i+n-1)*m+j;
    134             int t=(i+j)%2;
    135             //0为金色
    136             if(t==0)
    137             {
    138                 DC.AddEdge(src,id1,map[i][j]);    //
    139                 DC.AddEdge(id2,dst,map[i+n][j]);  //
    140                 DC.AddEdge(id1,id2,INF);
    141                 for(int k=0;k<4;k++)
    142                 {
    143                     int x=i+dx[k];
    144                     int y=j+dy[k];
    145                     if(x<1||x>n||y<1||y>m)  continue;
    146                     DC.AddEdge(id1,(x+n-1)*m+y,G);
    147                 }
    148             }
    149             else
    150             {
    151                 DC.AddEdge(src,id1,map[i+n][j]);
    152                 DC.AddEdge(id2,dst,map[i][j]);
    153                 DC.AddEdge(id1,id2,INF);
    154                 for(int k=0;k<4;k++)
    155                 {
    156                     int x=i+dx[k];
    157                     int y=j+dy[k];
    158                     if(x<1||x>n||y<1||y>m)  continue;
    159                     DC.AddEdge(id1,(x+n-1)*m+y,S);
    160                 }
    161             }
    162         }
    163 
    164         int ans=sum-DC.Maxflow(src,dst);
    165         printf("Case %d: %d
    ",++kase,ans);
    166     }
    167     return 0;
    168 }
  • 相关阅读:
    GCD的常用代码块
    多用字面量语法,少用与之等价的方法
    新建项目上下出现黑色块
    按钮UIButton的使用
    集成支付宝
    app生命周期之即将关闭
    苹果开发者计划申请材料准备(公司级)
    真机调试的一些问题记录~更新中
    iOS开发架构学习记录
    用枚举值表示状态、选项、状态码
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6701360.html
Copyright © 2011-2022 走看看