BZOJ1001: [BeiJing2006]狼抓兔子 (最小割转最短路)

浅析最大最小定理在信息学竞赛中的应用---周东

↑方法介绍
对于一个联通的平面图G(满足欧拉公式) 在s和t间新连一条边e;
然后建立一个原图的对偶图G*,G*中每一个点对应原图中每一个面,每一条边对应分割面的每一条边;
那么对偶图G*中,以原图s和t间边e新划分出的面作为起点(s*),最外的面作为终点(t*);
那么从s*到t*的每一条路都是原图G的一个割;
下图来自上方标出百度文库网址的ppt;
BZOJ1001: [BeiJing2006]狼抓兔子  (最小割转最短路) - 拟南芥 - 鲸头鹳
然后用堆(优先队列)优化的迪杰斯特拉,复杂度 O((m+n)logn) n为点数,m为边数...
 
嗯存一个堆优化迪杰斯特拉的代码...很久以前那个没有标签的一通好找..
 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 #define pa pair<int,int>
 9 int n,m,s,t;
10 struct node{
11     int y;
12     int next;
13     int v;
14 }e[6000100];
15 int head[2000100]={},tot=0,dis[2000100]={};
16 bool vis[2000100]={};
17 priority_queue< pa, vector< pa >, greater< pa > >q;
18 inline void init(int x,int y,int v){
19     e[++tot].y=y;
20     e[tot].next=head[x];
21     e[tot].v=v;
22     head[x]=tot;
23 }
24 inline int ge(int x,int y,int k){//x行,y列,在斜线的左(1)右(2);返回格子的编号
25     return 2*(x-1)*(m-1)+2*(y-1)+k;
26 }
27 /*
28 事实上如果按照从上到下从左到右来编号,在输入时的块编号是有规律的;
29 不一定要像上面一样这样找格子编号;
30 */
31 void doit(){
32     memset(dis,63,sizeof(dis));
33     int x,y;
34     dis[s]=0;
35     q.push(make_pair(0,s));
36     while(!q.empty()){
37         x=q.top().second;
38         q.pop();
39         if(vis[x]){
40             continue;
41         }
42         vis[x]=1;
43         for(int i=head[x];i;i=e[i].next){
44             y=e[i].y;
45             if(dis[y]>dis[x]+e[i].v){
46                 dis[y]=dis[x]+e[i].v;
47                 vis[y]=0;
48                 q.push(make_pair(dis[y],e[i].y));
49             }
50         }
51     }
52 }
53 int main(){
54     scanf("%d%d",&n,&m);
55     int v;
56     t=(m-1)*(n-1)*2+2;
57     s=t-1;
58     for(int i=1;i<=n;i++){
59         for(int j=1;j<m;j++){
60             scanf("%d",&v);
61             if(i==1){
62                 init(s,2*j,v);
63                 init(2*j,s,v);
64             }else if(i==n){
65                 init(ge(n-1,j,1),t,v);
66                 init(t,ge(n-1,j,1),v);
67             }else{
68                 init(ge(i-1,j,1),ge(i,j,2),v);
69                 init(ge(i,j,2),ge(i-1,j,1),v);
70             }
71         }
72     }
73     for(int i=1;i<n;i++){
74         for(int j=1;j<=m;j++){
75             scanf("%d",&v);
76             if(j==1){
77                 init(t,ge(i,1,1),v);
78                 init(ge(i,1,1),t,v);
79             }else if(j==m){
80                 init(ge(i,m-1,2),s,v);
81                 init(s,ge(i,m-1,2),v);
82             }else{
83                 init(ge(i,j-1,2),ge(i,j,1),v);
84                 init(ge(i,j,1),ge(i,j-1,2),v);
85             }
86         }
87     }
88     for(int i=1;i<n;i++){
89         for(int j=1;j<m;j++){
90             scanf("%d",&v);
91             init(ge(i,j,1),ge(i,j,2),v);
92             init(ge(i,j,2),ge(i,j,1),v);
93         }
94     }
95     doit();
96     printf("%d\n",dis[t]);
97     return 0;
98 }
View Code

 

posted @ 2017-11-04 16:59  鲸头鹳  阅读(247)  评论(0编辑  收藏  举报