zoukankan      html  css  js  c++  java
  • bzoj3144: [Hnoi2013]切糕(最小割)

    传送门

    据说这玩意儿叫切糕模型?

    我们可以看做有$P*Q$个网格,每个格子有$R$个点,在每一个格子中选一个点,且相邻的点距离不能超过$d$,求最小代价

    考虑如果没有限制条件怎么做。我们可以把每一个网格中的点都串成一条链,每一条边容量为该点的权值,如果一条边被割代表这个点被选,然后都连上源点和汇点,那么跑一个最小割就行了

    然后有了限制条件怎么做呢?我们令每一个点都向相邻的点连边,即令$(i,j,k)$向$(i',j',k-d)$连边,容量$inf$。那么,假设我们会选的点的距离超过了$d$,那么就意味着在原图中割掉的边的距离超过$d$,但因为每对距离为$d$的点间都连了容量为$inf$的边,所以仍然能够到达,那么这就不是一个最小割。

    具体我讲不太来,可以画一个图比较好理解

     1 // luogu-judger-enable-o2
     2 //minamoto
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<queue>
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    10 char buf[1<<21],*p1=buf,*p2=buf;
    11 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    12 inline int read(){
    13     #define num ch-'0'
    14     char ch;bool flag=0;int res;
    15     while(!isdigit(ch=getc()))
    16     (ch=='-')&&(flag=true);
    17     for(res=num;isdigit(ch=getc());res=res*10+num);
    18     (flag)&&(res=-res);
    19     #undef num
    20     return res;
    21 }
    22 const int N=100005,M=1000005;
    23 int head[N],Next[M],ver[M],edge[M],tot=1;
    24 int dep[N],cur[N],n,m,s,t,h,d;
    25 queue<int> q;
    26 inline void add(int u,int v,int e){
    27     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
    28     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;
    29 }
    30 bool bfs(){
    31     while(!q.empty()) q.pop();
    32     memset(dep,-1,sizeof(dep));
    33     for(int i=s;i<=t;++i) cur[i]=head[i];
    34     q.push(s),dep[s]=0;
    35     while(!q.empty()){
    36         int u=q.front();q.pop();
    37         for(int i=head[u];i;i=Next[i]){
    38             int v=ver[i];
    39             if(dep[v]<0&&edge[i]){
    40                 dep[v]=dep[u]+1,q.push(v);
    41                 if(v==t) return true;
    42             }
    43         }
    44     }
    45     return false;
    46 }
    47 int dfs(int u,int limit){
    48     if(u==t||!limit) return limit;
    49     int flow=0,f;
    50     for(int i=cur[u];i;i=Next[i]){
    51         int v=ver[i];cur[u]=i;
    52         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
    53             flow+=f,limit-=f;
    54             edge[i]-=f,edge[i^1]+=f;
    55             if(!limit) break;
    56         }
    57     }
    58     if(!flow) dep[u]=-1;
    59     return flow;
    60 }
    61 int dinic(){
    62     int flow=0;
    63     while(bfs()) flow+=dfs(s,inf);
    64     return flow;
    65 }
    66 #define id(i,j,k) (((i-1)*m+j-1)*h+k)
    67 int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
    68 int main(){
    69     //freopen("testdata.in","r",stdin);
    70     n=read(),m=read(),h=read(),d=read();
    71     s=0,t=n*m*h+1;
    72     for(int k=1;k<=h;++k)
    73     for(int i=1;i<=n;++i)
    74     for(int j=1;j<=m;++j){
    75         int x=read();
    76         if(k==1) add(s,id(i,j,k),x);
    77         else add(id(i,j,k-1),id(i,j,k),x);
    78         if(k==h) add(id(i,j,k),t,inf);
    79     }
    80     for(int i=1;i<=n;++i)
    81     for(int j=1;j<=m;++j)
    82     for(int k=d+1;k<=h;++k)
    83     for(int l=0;l<4;++l){
    84         int x=i+dx[l],y=j+dy[l];
    85         if(x>=1&&x<=n&&y>=1&&y<=m) add(id(i,j,k),id(x,y,k-d),inf);
    86     }
    87     printf("%d
    ",dinic());
    88     return 0;
    89 }
  • 相关阅读:
    setjmp()和longjmp()函数
    C语言过程活动记录
    【剑指Offer】字符串的排列
    python剑指offer系列二叉树中和为某一值的路径
    二叉搜索树的后续遍历
    如何设置学习率
    各种机器学习算法的优缺点(未完成)
    机器学习中梯度下降法和牛顿法的比较
    特征图大小的计算
    为什么L1稀疏,L2平滑?
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9566043.html
Copyright © 2011-2022 走看看