[BeiJing2006]狼抓兔子
Description
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击这些兔子.当然 为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔 子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.接下来分三部分 第一部分共N行,每行M-1个数,表示横向道路的权值. 第二部分共N-1行,每行M个数,表示纵向道路的权值. 第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
平面图最大流转化为最短路问题。
heap+dijkstra优化。
第一次使用STL中的heap操作,太简便了,不过也编了个最小堆。
STL调用<algorithm>中的pop_heap(begin,last,cmp)去除最小元素,push_heap(begin,last,cmp)将last-1上的元素加入堆中:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<fstream> 6 #define Edgsize 6000000 7 #define Nodesize 2000000 8 #define Maxint 100000000 9 10 using namespace std; 11 //ifstream cin("cin.in"); 12 13 int n,m,S,T; 14 int to[Edgsize],next[Edgsize],weight[Edgsize],head[Nodesize],edgs=0; 15 int dis[Nodesize]; 16 typedef struct { 17 int num,d; 18 }Heap;Heap heap[Nodesize],temp; 19 20 int seat(int x,int y,int z){ 21 if(z==1) return (x-1)*(m-1)+y; 22 else return (n-1)*(m-1)+(x-1)*(m-1)+y; 23 } 24 25 void Addedg(int u,int v,int d){ 26 edgs++;to[edgs]=v;next[edgs]=head[u];weight[edgs]=d;head[u]=edgs; 27 edgs++;to[edgs]=u;next[edgs]=head[v];weight[edgs]=d;head[v]=edgs; 28 } 29 30 int ans=Maxint; 31 void Init(){ 32 //cout<<" sdf";system("pause"); 33 cin>>n>>m; 34 35 S=(n-1)*(m-1)*2+1;T=S+1; 36 memset(head,-1,sizeof(head)); 37 38 int d; 39 40 if(n==1||m==1) 41 { 42 for(int i=1;i<n||i<m;++i) 43 {cin>>d;if(d<ans) ans=d;}return ; 44 } 45 46 for(int i=1;i<=n;++i) 47 for(int j=1;j<m;++j) 48 { 49 cin>>d; 50 if(i==1) Addedg(S,seat(1,j,1),d); 51 else if(i==n) Addedg(seat(i-1,j,2),T,d); 52 else Addedg(seat(i-1,j,2),seat(i,j,1),d); 53 } 54 55 for(int i=1;i<n;++i) 56 for(int j=1;j<=m;++j) 57 { 58 cin>>d; 59 if(j==1) Addedg(seat(i,j,2),T,d); 60 else if(j==m) Addedg(seat(i,j-1,1),S,d); 61 else Addedg(seat(i,j-1,1),seat(i,j,2),d); 62 } 63 64 for(int i=1;i<n;++i) 65 for(int j=1;j<m;++j) 66 { 67 cin>>d; 68 Addedg(seat(i,j,1),seat(i,j,2),d); 69 } 70 71 } 72 73 bool cmp(Heap a,Heap b){ 74 return a.d>b.d; 75 } 76 77 int size=1; 78 void Dijkstra(){ 79 for(int i=1;i<=T;++i) 80 dis[i]=Maxint; 81 82 if(n==1||m==1) {cout<<0<<endl;return ;} 83 84 dis[S]=0;heap[1].num=S;heap[1].d=0; 85 while(size) 86 { 87 temp=heap[1]; 88 // if(heap[1].num==T) {cout<<dis[T]<<endl;return ;} 89 pop_heap(heap+1,heap+1+size,cmp); 90 size--;//cout<<size<<" dsfg "<<endl; 91 92 for(int it=head[temp.num];it!=-1;it=next[it]) 93 if(dis[to[it]]>dis[temp.num]+weight[it]) 94 { 95 96 dis[to[it]]=dis[temp.num]+weight[it]; 97 // cout<<from[it]<<" "<<to[it]<<" "<<dis[to[it]]<<endl; 98 size++; 99 heap[size].num=to[it];heap[size].d=dis[to[it]]; 100 101 push_heap(heap+1,heap+1+size,cmp); 102 } 103 } 104 cout<<dis[T]<<endl; 105 106 } 107 108 int main() 109 { 110 Init(); 111 if(ans!=Maxint) {cout<<ans<<endl;return 0;} 112 113 Dijkstra(); 114 //system("pause"); 115 return 0; 116 }
手写堆:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<fstream> 6 #define Edgsize 6000000 7 #define Nodesize 2000000 8 #define Maxint 100000000 9 10 using namespace std; 11 //ifstream cin("cin.in"); 12 13 int n,m,S,T; 14 int to[Edgsize],next[Edgsize],weight[Edgsize],head[Nodesize],edgs=0; 15 int dis[Nodesize]; 16 typedef struct { 17 int num,d; 18 }Heap;Heap heap[Nodesize],temp; 19 20 int seat(int x,int y,int z){ 21 if(z==1) return (x-1)*(m-1)+y; 22 else return (n-1)*(m-1)+(x-1)*(m-1)+y; 23 } 24 25 void Addedg(int u,int v,int d){ 26 edgs++;to[edgs]=v;next[edgs]=head[u];weight[edgs]=d;head[u]=edgs; 27 edgs++;to[edgs]=u;next[edgs]=head[v];weight[edgs]=d;head[v]=edgs; 28 } 29 30 int ans=Maxint; 31 void Init(){ 32 //cout<<" sdf";system("pause"); 33 cin>>n>>m; 34 35 S=(n-1)*(m-1)*2+1;T=S+1; 36 memset(head,-1,sizeof(head)); 37 38 int d; 39 40 if(n==1||m==1) 41 { 42 for(int i=1;i<n||i<m;++i) 43 {cin>>d;if(d<ans) ans=d;}return ; 44 } 45 46 for(int i=1;i<=n;++i) 47 for(int j=1;j<m;++j) 48 { 49 cin>>d; 50 if(i==1) Addedg(S,seat(1,j,1),d); 51 else if(i==n) Addedg(seat(i-1,j,2),T,d); 52 else Addedg(seat(i-1,j,2),seat(i,j,1),d); 53 } 54 55 for(int i=1;i<n;++i) 56 for(int j=1;j<=m;++j) 57 { 58 cin>>d; 59 if(j==1) Addedg(seat(i,j,2),T,d); 60 else if(j==m) Addedg(seat(i,j-1,1),S,d); 61 else Addedg(seat(i,j-1,1),seat(i,j,2),d); 62 } 63 64 for(int i=1;i<n;++i) 65 for(int j=1;j<m;++j) 66 { 67 cin>>d; 68 Addedg(seat(i,j,1),seat(i,j,2),d); 69 } 70 71 } 72 73 74 int len=1; 75 void Down(int site){ 76 77 while(1) 78 {//cout<<"down"<<endl; 79 int least=site,left=2*site,right=2*site+1; 80 if(left<=len&&heap[left].d<heap[least].d) least=left; 81 if(right<=len&&heap[right].d<heap[least].d) least=right; 82 83 if(least!=site) 84 { 85 swap(heap[site],heap[least]); 86 site=least; 87 } 88 else break; 89 90 } 91 92 } 93 94 void Up(int site){ 95 int f=site/2; 96 while(f>0&&heap[site].d<heap[f].d) 97 { 98 swap(heap[site],heap[f]); 99 site=f; 100 f/=2; 101 } 102 } 103 104 void Delete_min(int l){ 105 if(l==0) return ; 106 swap(heap[1],heap[l+1]); 107 Down(1); 108 } 109 110 111 void Dijkstra(){ 112 for(int i=1;i<=T;++i) 113 dis[i]=Maxint; 114 heap[1].num=S;heap[1].d=0;dis[S]=0; 115 116 for(int i=1;i<=T&&len>0;++i) 117 { 118 temp=heap[1]; 119 len--; 120 Delete_min(len); //cout<<" sdfg"<<endl; 121 122 for(int j=head[temp.num];j!=-1;j=next[j]) 123 if(dis[to[j]]>dis[temp.num]+weight[j]) 124 { 125 dis[to[j]]=dis[temp.num]+weight[j]; 126 len++;//cout<<len<<" "<<endl; 127 heap[len].num=to[j];heap[len].d=dis[to[j]]; 128 Up(len); 129 } 130 // system("pause"); 131 } 132 cout<<dis[T]<<endl; 133 } 134 135 int main(){ 136 Init();///cout<<n<<" "<<m<<endl; 137 if(ans!=Maxint) {cout<<ans<<endl;return 0;} 138 Dijkstra(); 139 //system("pause"); 140 return 0; 141 142 }