zoukankan      html  css  js  c++  java
  • 【BZOJ 3144】 3144: [Hnoi2013]切糕 (最小割模型)

    3144: [Hnoi2013]切糕

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1764  Solved: 965

    Description

    Input

    第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。 
    100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。

    Output

    仅包含一个整数,表示在合法基础上最小的总不和谐值。

    Sample Input

    2 2 2
    1
    6 1
    6 1
    2 6
    2 6

    Sample Output

    6

    HINT

    最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1

    Source

     
     
    【题意】
      三维的图,每个x,y选一个高度,每个高度有一个值v[x][y][h],相邻的(x,y)选的h的差要小于等于D,使得总的v最小,问最小值。
     
    【分析】
      我不知道的最小割经典模型?
      

     这个题是个挺经典的最小割。

      这个题的关键是如何限制h之差不超过d。首先我们按高度分层,每层的点向下一层相同位置的点连边,边权设为点权(也就是说我们要多设一层),然后如果我们割掉这条边就意味着选择了下面这个点。然后,对于h之差的限制,我们把k+d层的点向k层的四周的点连+oo边,也就是说如果我们割掉了一条边,就不能选择+oo的边连接的上面的边,因为选择了这条边,如果再选择上面的边的话,就不能构成割了,因为流还是可以经过那条+oo的边流回来。其实类比一下最大权独立集的话,这条+oo的边的意义就是选了某个点以后,就不能选和它相差超过d的点了。

    来自:http://www.cnblogs.com/zig-zag/archive/2013/05/13/3076563.html

      
      这样子的话,割掉超过d的边,还是割不断st到ed的路径的。
     
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 50
      9 #define INF 0xfffffff
     10 
     11 int mymin(int x,int y) {return x<y?x:y;}
     12 
     13 int num[Maxn][Maxn][Maxn],v[Maxn][Maxn][Maxn];
     14 
     15 struct node
     16 {
     17     int x,y,f,next,o;
     18 }t[Maxn*Maxn*Maxn*20];
     19 int len,first[Maxn*Maxn*Maxn];
     20 
     21 void ins(int x,int y,int f)
     22 {
     23     t[++len].x=x;t[len].y=y;t[len].f=f;
     24     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     25     t[++len].x=y;t[len].y=x;t[len].f=0;
     26     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     27 }
     28 
     29 int st,ed;
     30 int dis[Maxn*Maxn*Maxn];
     31 queue<int > q;
     32 bool bfs()
     33 {
     34     for(int i=1;i<=ed;i++) dis[i]=-1;
     35     while(!q.empty()) q.pop();
     36     dis[st]=0;q.push(st);
     37     while(!q.empty())
     38     {
     39         int x=q.front();
     40         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     41         {
     42             int y=t[i].y;
     43             if(dis[y]==-1)
     44             {
     45                 dis[y]=dis[x]+1;
     46                 q.push(y);
     47             }
     48         }
     49         q.pop();
     50     }
     51     if(dis[ed]==-1) return 0;
     52     return 1;
     53 }
     54 
     55 int ffind(int x,int flow)
     56 {
     57     if(x==ed) return flow;
     58     int now=0;
     59     for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     60     {
     61         int y=t[i].y;
     62         if(dis[y]==dis[x]+1)
     63         {
     64             int a=ffind(y,mymin(flow-now,t[i].f));
     65             t[i].f-=a;
     66             t[t[i].o].f+=a;
     67             now+=a;
     68         }
     69         if(now==flow) break;
     70     }
     71     if(now==0) dis[x]=-1;
     72     return now;
     73 }
     74 
     75 void output()
     76 {
     77     for(int i=1;i<=len;i+=2)
     78     {
     79         printf("%d -> %d %d
    ",t[i].x,t[i].y,t[i].f);
     80     }printf("
    ");
     81 }
     82 
     83 int ans=0;
     84 void max_flow()
     85 {
     86     while(bfs())
     87     {
     88         ans+=ffind(st,INF);
     89     }
     90     printf("%d
    ",ans);
     91 }
     92 
     93 int main()
     94 {
     95     int n,m,h,d;
     96     scanf("%d%d%d",&n,&m,&h);
     97     scanf("%d",&d);
     98     int cnt=0;
     99     st=n*m*h+1;ed=st+1;
    100     for(int k=1;k<=h;k++)
    101     {
    102        for(int i=1;i<=n;i++)
    103         for(int j=1;j<=m;j++)
    104         {
    105             scanf("%d",&v[i][j][k]);
    106             num[i][j][k]=++cnt;
    107             if(k!=1) ins(num[i][j][k-1],num[i][j][k],v[i][j][k]);
    108             else ins(st,num[i][j][k],v[i][j][k]);
    109             if(k==h) ins(num[i][j][k],ed,INF);
    110             if(i!=1&&k>d) ins(num[i][j][k],num[i-1][j][k-d],INF);
    111             if(i!=n&&k>d) ins(num[i][j][k],num[i+1][j][k-d],INF);
    112             if(j!=1&&k>d) ins(num[i][j][k],num[i][j-1][k-d],INF);
    113             if(j!=m&&k>d) ins(num[i][j][k],num[i][j+1][k-d],INF);
    114         }
    115     }
    116     max_flow();
    117     return 0;
    118 }
    View Code

    2017-03-29 14:57:42

  • 相关阅读:
    第一学期心得
    第十三次作业
    第十二次作业
    第十一次作业
    第十次作业
    第九次作业
    第八次作业
    第七次作业
    第六次作业
    第五次作业
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6639800.html
Copyright © 2011-2022 走看看