首页 > 代码库 > bzoj 3144: [Hnoi2013]切糕 最小割

bzoj 3144: [Hnoi2013]切糕 最小割

3144: [Hnoi2013]切糕

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 681  Solved: 375
[Submit][Status]

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

 

  一类经典的方案选择型最小割,感觉,非常神奇,不过这个是稠密图把我以前的dinic直接卡TLE了,发现一定要判断maxf==0时直接退出。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 50#define MAXH 50#define MAXE MAXV*10#define MAXV MAXN*MAXN*MAXH#define INF 0x3f3f3f3fconst int mov[4][2]={{0,1},{1,0},{-1,0},{0,-1}};struct Edge{        int np,val;        Edge *next,*neg;}E[MAXE],*V[MAXV];int sour,sink=1;int tope=-1;void addedge(int x,int y,int z){//        printf("Add:%d %d %d\n",x,y,z);        E[++tope].np=y;        E[tope].val=z;        E[tope].next=V[x];        V[x]=&E[tope];        E[++tope].np=x;        E[tope].val=0;        E[tope].next=V[y];        V[y]=&E[tope];        V[x]->neg=V[y];        V[y]->neg=V[x];}int q[MAXV];int vis[MAXV],bfstime=0;int lev[MAXV];int bfs(){        int head=-1,tail=0;        Edge *ne;        int now;        q[0]=sour;        vis[sour]=++bfstime;        while (head<tail)        {                now=q[++head];                for (ne=V[now];ne;ne=ne->next)                {                        if (!ne->val || vis[ne->np]==bfstime)continue;                        vis[ne->np]=bfstime;                        q[++tail]=ne->np;                        lev[ne->np]=lev[now]+1;                }        }        return vis[sink]==bfstime;}int dfs(int now,int maxf){        int t,ret=0;        if (now==sink)return maxf;        Edge *ne;        for (ne=V[now];maxf && ne;ne=ne->next)        {                if (!ne->val || lev[ne->np]!=lev[now]+1)continue;                t=dfs(ne->np,min(maxf,ne->val));                ne->val-=t;                ne->neg->val+=t;                maxf-=t;                ret+=t;        }        if (maxf)lev[now]=-1;        return ret;}int dinic(){        int ret=0;        while (bfs())        {                ret+=dfs(sour,INF);        }        return ret;}int n,m,h;int gid(int x,int y,int z){        return 2+x*m+y+z*m*n;}int a[MAXN][MAXN][MAXH];int main(){        freopen("input.txt","r",stdin);        int i,j,k,k2,x,y,z;        scanf("%d%d%d",&n,&m,&h);        int d;        scanf("%d",&d);        for (k=1;k<=h;k++)                for (i=1;i<=n;i++)                        for (j=1;j<=m;j++)                                {                                        scanf("%d",&a[i][j][k]);                                        addedge(gid(i,j,k-1),gid(i,j,k),a[i][j][k]);                                }        for (i=1;i<=n;i++)                for (j=1;j<=m;j++)                        for (k=1;k+d<=h;k++)                                for (k2=0;k2<4;k2++)                                        if (i+mov[k2][0]>0 && i+mov[k2][0]<=n && j+mov[k2][1]>0 && j+mov[k2][1]<=m)                                        {                                        //        addedge(gid(i,j,k),gid(i+mov[k2][0],j+mov[k2][1],k+d),INF);                                                addedge(gid(i,j,k+d),gid(i+mov[k2][0],j+mov[k2][1],k),INF);                                        }        for (i=1;i<=n;i++)                for (j=1;j<=m;j++)                {                        addedge(sour,gid(i,j,0),INF);                        addedge(gid(i,j,h),sink,INF);                }        printf("%d\n",dinic());}

 

bzoj 3144: [Hnoi2013]切糕 最小割