zoukankan      html  css  js  c++  java
  • bzoj 3144 [Hnoi2013]切糕

    最小割。

    题意简化一下就是:给一个矩阵,每个点给出一些带编号的选择,每个选择有权值,现在对于每个点做出一个选择,使得相邻点的选择的编号差小于等于d,并且使总权值最大。

    首先考虑没有编号差小于等于d的限制,将一个点拆成选择个点,对于一个点的所有选择点,连成一条链,权值反应在边上,首尾与S,T相连,这样求一个最小割就是答案。

    再考虑有了限制,某个点选了第i个选择,与它相邻的点就必须选在[i-d,i+d]中的选择。从当前点的i号点向相邻点的i-d号点连一条正无穷的边,再求最小割就好了。

    这时如果割掉i的边,那么存在一条流从当前点i号点流向相邻点i-d号点,相邻点的i+d+1号点流向当前点的i+1号点,这样就保证选了i相邻点必须选[i-d,i+d]。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int dian=70005;
      8 const int bian=500005;
      9 const int INF=0x3f3f3f3f;
     10 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian],cr[dian];
     11 int n,m,hh,tot,d,aa;
     12 int S,T;
     13 int bh(int a,int b,int c){
     14     return (a-1)*m*hh+(b-1)*hh+c;
     15 }
     16 void add(int a,int b,int c){
     17     tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot;
     18     tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot;
     19 }
     20 bool tell(){
     21     memset(ch,-1,sizeof(ch));
     22     queue<int>q;
     23     q.push(S);
     24     ch[S]=0;
     25     while(!q.empty()){
     26         int t=q.front();
     27         q.pop();
     28         for(int i=h[t];i;i=nxt[i])
     29             if(ch[ver[i]]==-1&&val[i]){
     30                 ch[ver[i]]=ch[t]+1;
     31                 q.push(ver[i]);
     32             }
     33     }
     34     return ch[T]!=-1;
     35 }
     36 int zeng(int a,int b){
     37     if(a==T)
     38         return b;
     39     int r=0;
     40     for(int i=cr[a];i&&b>r;i=nxt[i])
     41         if(ch[ver[i]]==ch[a]+1&&val[i]){
     42             int t=zeng(ver[i],min(b-r,val[i]));
     43             val[i]-=t,r+=t,val[i^1]+=t;
     44             if(val[i])
     45                 cr[a]=i;
     46         }
     47     if(!r)
     48         ch[a]=-1;
     49     return r;
     50 }
     51 int dinic(){
     52     int r=0,t;
     53     while(tell()){
     54         for(int i=1;i<=n*m*hh+2;i++)
     55             cr[i]=h[i];
     56         while(t=zeng(S,INF))
     57             r+=t;
     58     }
     59     return r;
     60 }
     61 int main(){
     62     memset(h,0,sizeof(h));
     63     memset(nxt,0,sizeof(nxt));
     64     tot=1;
     65     scanf("%d%d%d",&n,&m,&hh);
     66     S=n*m*hh+1,T=n*m*hh+2;
     67     for(int i=1;i<=n;i++)
     68         for(int j=1;j<=m;j++)
     69             add(S,bh(i,j,1),INF);
     70     scanf("%d",&d);
     71     for(int i=1;i<=hh;i++)
     72         for(int j=1;j<=n;j++)
     73             for(int k=1;k<=m;k++){
     74                 scanf("%d",&aa);
     75                 if(i!=hh)
     76                     add(bh(j,k,i),bh(j,k,i+1),aa);
     77                 else
     78                     add(bh(j,k,i),T,aa);
     79             }
     80     for(int i=1;i<=n;i++)
     81         for(int j=1;j<=m;j++){
     82             if(i-1>=1){
     83                 for(int k=1;k<=d;k++)
     84                     add(bh(i,j,k),bh(i-1,j,1),INF);
     85                 for(int k=d+1;k<=hh;k++)
     86                     add(bh(i,j,k),bh(i-1,j,k-d),INF);
     87             }
     88             if(i+1<=n){
     89                 for(int k=1;k<=d;k++)
     90                     add(bh(i,j,k),bh(i+1,j,1),INF);
     91                 for(int k=d+1;k<=hh;k++)
     92                     add(bh(i,j,k),bh(i+1,j,k-d),INF);
     93             }
     94             if(j-1>=1){
     95                 for(int k=1;k<=d;k++)
     96                     add(bh(i,j,k),bh(i,j-1,1),INF);
     97                 for(int k=d+1;k<=hh;k++)
     98                     add(bh(i,j,k),bh(i,j-1,k-d),INF);
     99             }
    100             if(j+1<=m){
    101                 for(int k=1;k<=d;k++)
    102                     add(bh(i,j,k),bh(i,j+1,1),INF);
    103                 for(int k=d+1;k<=hh;k++)
    104                     add(bh(i,j,k),bh(i,j+1,k-d),INF);
    105             }
    106         }
    107     printf("%d",dinic());
    108     return 0;
    109 }
  • 相关阅读:
    数据结构实验之栈与队列四:括号匹配(SDUT 2134)
    从 s 点到 t 点的最短路(简单模板)(迪杰斯特拉)
    畅通工程续(HDU 1874)(简单最短路)
    Til the Cows Come Home ( POJ 2387) (简单最短路 Dijkstra)
    顺序表应用7:最大子段和之分治递归法(SDUT 3664)
    Java面向对象4(P~U)
    House Lawn Kattis
    Jumbled String (Kattis
    队列详解及java实现
    栈详解及java实现
  • 原文地址:https://www.cnblogs.com/dugudashen/p/6276850.html
Copyright © 2011-2022 走看看