bzoj 1001 [BeiJing2006]狼抓兔子
平面图最小割转对偶图最短路。
初看是一个裸的最小割,但数据范围1000000个点……
在原平面图上加入一条S到T的边,形成一个新区域。
将图上每个区域(二维)看做一个点(包括新区域和无限大的区域),区域边界看做边,边权为边界所对应原图中的边的边权,新建图。
删掉新区域和无限大区域之间的边。
此时原图最小割等于新图上新区域点到无限大区域点的最短路。
直观理解一下感觉挺对。
至于怎么实现上面的步骤,本题很简单随便搞一搞就行了,一般平面图的话就不(gen)再(ben)赘(bu)述(hui)了。
最后注意1*m和n*1的情况,此时根本没有区域,要特判。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int dian=2000005; 8 const int bian=8000005; 9 struct nd{ 10 int bh; 11 int diss; 12 bool operator < (const nd &rhs)const{ 13 return rhs.diss<diss; 14 } 15 }; 16 int h[dian],nxt[bian],ver[bian],val[bian],dis[dian],v[dian]; 17 int n,m,tot,aa; 18 int S,T; 19 void add(int a,int b,int c){ 20 tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot; 21 } 22 void dijkstra(){ 23 memset(dis,0x3f,sizeof(dis)); 24 memset(v,0,sizeof(v)); 25 priority_queue<nd>q; 26 dis[S]=0; 27 nd hhd; 28 hhd.bh=S; 29 hhd.diss=0; 30 q.push(hhd); 31 while(!q.empty()){ 32 hhd=q.top(); 33 q.pop(); 34 int x=hhd.bh; 35 if(v[x]) 36 continue; 37 v[x]=1; 38 for(int i=h[x];i;i=nxt[i]){ 39 int y=ver[i]; 40 if(dis[y]>dis[x]+val[i]){ 41 dis[y]=dis[x]+val[i]; 42 hhd.bh=y; 43 hhd.diss=dis[y]; 44 q.push(hhd); 45 } 46 } 47 } 48 } 49 int main(){ 50 memset(h,0,sizeof(h)); 51 memset(nxt,0,sizeof(nxt)); 52 tot=0; 53 scanf("%d%d",&n,&m); 54 if(n==1){ 55 int la=0x3f3f3f3f; 56 for(int i=1;i<m;i++){ 57 scanf("%d",&aa); 58 la=min(la,aa); 59 } 60 printf("%d",la); 61 return 0; 62 } 63 if(m==1){ 64 int la=0x3f3f3f3f; 65 for(int i=1;i<n;i++){ 66 scanf("%d",&aa); 67 la=min(la,aa); 68 } 69 printf("%d",la); 70 return 0; 71 } 72 S=n*m*2+1,T=n*m*2+2; 73 for(int i=1;i<m;i++){ 74 scanf("%d",&aa); 75 add(S,i,aa); 76 add(i,S,aa); 77 } 78 for(int i=2;i<n;i++) 79 for(int j=1;j<m;j++){ 80 scanf("%d",&aa); 81 add(n*m+(i-2)*m+j,(i-1)*m+j,aa); 82 add((i-1)*m+j,n*m+(i-2)*m+j,aa); 83 } 84 for(int i=1;i<m;i++){ 85 scanf("%d",&aa); 86 add(n*m+(n-2)*m+i,T,aa); 87 add(T,n*m+(n-2)*m+i,aa); 88 } 89 for(int i=1;i<n;i++) 90 for(int j=1;j<=m;j++){ 91 scanf("%d",&aa); 92 if(j==1){ 93 add(T,n*m+(i-1)*m+j,aa); 94 add(n*m+(i-1)*m+j,T,aa); 95 } 96 else if(j==m){ 97 add((i-1)*m+j-1,S,aa); 98 add(S,(i-1)*m+j-1,aa); 99 } 100 else{ 101 add((i-1)*m+j-1,n*m+(i-1)*m+j,aa); 102 add(n*m+(i-1)*m+j,(i-1)*m+j-1,aa); 103 } 104 } 105 for(int i=1;i<n;i++) 106 for(int j=1;j<m;j++){ 107 scanf("%d",&aa); 108 add(n*m+(i-1)*m+j,(i-1)*m+j,aa); 109 add((i-1)*m+j,n*m+(i-1)*m+j,aa); 110 } 111 dijkstra(); 112 printf("%d",dis[T]); 113 return 0; 114 }