1. 程式人生 > >BZOJ1001: [BeiJing2006]狼抓兔子 (最小割轉最短路)

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

pty closed bsp ini 分割 pan void define 最短

淺析最大最小定理在信息學競賽中的應用---周東

↑方法介紹 對於一個聯通的平面圖G(滿足歐拉公式) 在s和t間新連一條邊e; 然後建立一個原圖的對偶圖G*,G*中每一個點對應原圖中每一個面,每一條邊對應分割面的每一條邊; 那麽對偶圖G*中,以原圖s和t間邊e新劃分出的面作為起點(s*),最外的面作為終點(t*); 那麽從s*到t*的每一條路都是原圖G的一個割; 下圖來自上方標出百度文庫網址的ppt; 技術分享 然後用堆(優先隊列)優化的迪傑斯特拉,復雜度 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

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