1. 程式人生 > >【bzoj3144】[Hnoi2013]切糕 最小割

【bzoj3144】[Hnoi2013]切糕 最小割

jpg tin use esp pos 題意 clas mat tput

[Hnoi2013]切糕

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 2228 Solved: 1220
[Submit][Status][Discuss]

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

題解:

  題意表示看不懂了,語文水平差,沒辦法。

  切割就是每條豎線上選擇一個點來斷開,

  如果沒有這個限制是什麽,就是直接一層中的點向下一層對應的點連邊

  那麽限制的話就是當前的點割了不能割

  那麽就是也可以轉換為,割了這條邊,與其相距d的邊割了無效

  發現一個點向上向下都制約D和每個點都只向下制約是等價的

  所以從該點向下d連一條無窮的邊,不能割

當時看這個人才會的

技術分享圖片

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 
  7 #define rad 100000000
  8 #define
inf 1000000000 9 #define ll long long 10 #define eps 1e-10 11 #define pa pair<ll,int> 12 using namespace std; 13 ll read() 14 { 15 ll x=0,f=1;char ch=getchar(); 16 while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} 17 while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} 18 return x*f; 19 } 20 21 int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; 22 int P,Q,r,d,T,cnt=1; 23 int f[45][45][45]; 24 int cur[100005],last[100005],h[100005],q[100005]; 25 26 struct edge{ 27 int to,next,v; 28 }e[1000005]; 29 int p(int x,int y,int z) 30 { 31 if(z==0)return 0; 32 return (z-1)*P*Q+(x-1)*Q+y; 33 } 34 void insert(int u,int v,int w) 35 { 36 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w; 37 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=0; 38 } 39 void build() 40 { 41 for(int i=1;i<=P;i++) 42 for(int j=1;j<=Q;j++) 43 { 44 for(int k=1;k<=r;k++) 45 { 46 insert(p(i,j,k-1),p(i,j,k),f[i][j][k]); 47 if(k>d) 48 for(int dir=0;dir<4;dir++) 49 { 50 int nx=i+xx[dir],ny=j+yy[dir]; 51 if(nx<1||ny<1||nx>P||ny>Q)continue; 52 insert(p(i,j,k),p(nx,ny,k-d),inf); 53 } 54 } 55 insert(p(i,j,r),T,inf); 56 } 57 } 58 bool bfs() 59 { 60 int head=0,tail=1; 61 memset(h,-1,sizeof(h)); 62 q[0]=0;h[0]=0; 63 while(head!=tail) 64 { 65 int now=q[head];head++; 66 for(int i=last[now];i;i=e[i].next) 67 if(h[e[i].to]==-1&&e[i].v) 68 { 69 h[e[i].to]=h[now]+1; 70 q[tail++]=e[i].to; 71 } 72 } 73 return h[T]!=-1; 74 } 75 int dfs(int x,int f) 76 { 77 if(x==T)return f; 78 int w,used=0; 79 for(int i=cur[x];i;i=e[i].next) 80 if(h[x]+1==h[e[i].to]) 81 { 82 w=dfs(e[i].to,min(f-used,e[i].v)); 83 used+=w;e[i].v-=w;e[i^1].v+=w; 84 if(e[i].v)cur[x]=i; 85 if(used==f)return f; 86 } 87 if(!used)h[x]=-1; 88 return used; 89 } 90 int dinic() 91 { 92 int tmp=0; 93 while(bfs()) 94 { 95 for(int i=0;i<=T;i++)cur[i]=last[i]; 96 tmp+=dfs(0,inf); 97 } 98 return tmp; 99 } 100 int main() 101 { 102 P=read();Q=read();r=read();T=P*Q*r+1; 103 d=read(); 104 for(int i=1;i<=r;i++) 105 for(int j=1;j<=P;j++) 106 for(int k=1;k<=Q;k++) 107 f[j][k][i]=read(); 108 build(); 109 printf("%d\n",dinic()); 110 }

【bzoj3144】[Hnoi2013]切糕 最小割