[BZOJ 3144][Hnoi2013]切糕(最小割)

Description


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

Solution


據說這是個經典模型QvQ
Edges數組沒開夠,沒有1A…以後記得要把反向邊算進去啊
寫了一個number函數,給網格編號的時候用起來比較順手代碼看起來也不會那麼無腦,可以發揚一下…

建圖比較神奇
大概就是把同一個位置相鄰層數的點連成一條鏈,再和s.t連起來(這樣就只能割其中的一條邊了)
再把第k層每個位置,與周圍的k-d層連一條INF的邊(爲了保證相鄰的位置高度差不超過d)…如果不是很懂可以畫圖推一下
然後求最小割

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#define MAXN 100000
#define Min(a,b) (a<b?a:b)
#define INF 0x3f3f3f3f
using namespace std;
int p,q,r,d,s,t;
int a[41][41][41];
int head[MAXN],level[MAXN],cnt=0;
struct Node{
    int next,to,cap;
}Edges[MAXN*2];
void addedge(int u,int v,int w)
{
    Edges[cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].to=v;
    Edges[cnt++].cap=w;
}
void Insert(int u,int v,int w)
{
    addedge(u,v,w);
    addedge(v,u,0);
}
int number(int i,int j,int k)
{
    return (k-1)*p*q+(i-1)*q+j;
}
bool bfs()
{
    memset(level,-1,sizeof(level));
    queue<int>q;
    q.push(s);
    level[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        for(int i=head[u];~i;i=Edges[i].next)
        {
            int v=Edges[i].to;
            if(level[v]==-1&&Edges[i].cap)
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
        q.pop();
    }
    if(level[t]==-1)return false;
    return true;
}
int dfs(int u,int flow)
{
    if(u==t)return flow;
    int mf=0,d=0;
    for(int i=head[u];~i&&mf<flow;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(level[v]==level[u]+1&&Edges[i].cap)
        {
            d=dfs(v,Min(Edges[i].cap,flow-mf));
            Edges[i].cap-=d;
            Edges[i^1].cap+=d;
            mf+=d;
        }
    }
    if(!mf)level[u]=-1;
    return mf;
}
int Dinic()
{
    int ans=0,d=0;
    while(bfs())
    {
        while(d=dfs(s,INF))
        ans+=d;
    }
    return ans;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d%d",&p,&q,&r,&d);
    for(int k=1;k<=r;k++)
    {
        for(int i=1;i<=p;i++)
        for(int j=1;j<=q;j++)
        scanf("%d",&a[k][i][j]);
    }
    s=0,t=number(1,1,r+1);
    for(int i=1;i<=p;i++)
    for(int j=1;j<=q;j++)
    {
        for(int k=1;k<=r;k++)
        {
            int u=number(i,j,k),v=number(i,j,k-1);
            if(k>1)Insert(v,u,a[k][i][j]);
            else Insert(s,u,a[k][i][j]);
            if(i>1&&k>d)v=number(i-1,j,k-d),Insert(u,v,INF);
            if(j>1&&k>d)v=number(i,j-1,k-d),Insert(u,v,INF);
            if(i<p&&k>d)v=number(i+1,j,k-d),Insert(u,v,INF);
            if(j<q&&k>d)v=number(i,j+1,k-d),Insert(u,v,INF);
            if(k==r)Insert(u,t,INF);
        }
    }
    printf("%d",Dinic());
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章