bzoj 1001: [BeiJing2006]狼抓兔子
真不知道bzoj为什么要把这么难的题放第一题,就这道题弄得我好久都不敢刷bzoj。。
一道很明显的网络流题,最大流最小割定理
只不过用网络流是过不了的,因为数据范围过大
但由于这是一个平面图,于是可以另辟蹊径
详情请搜:周冬《两极相通——浅析最大—最小定理在信息学竞赛中的应用》
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = 1003; 6 const int M = 2000005; 7 const int inf = 0x3f3f3f3f; 8 int head[M]; 9 struct node 10 { 11 int to,next,val; 12 }g[M + M]; 13 int m,n,nm,num; 14 int dis[M],que[M]; 15 bool flag[M]; 16 void add(int s,int e,int v) 17 { 18 g[num].to = e; 19 g[num].val = v; 20 g[num].next = head[s]; 21 head[s] = num ++; 22 } 23 int nextint() 24 { 25 int ret; 26 char c; 27 while((c = getchar()) > '9' || c < '0') 28 ; 29 ret = c - '0'; 30 while((c = getchar()) >= '0' && c <= '9') 31 ret = ret * 10 + c - '0'; 32 return ret; 33 } 34 void build() 35 { 36 scanf("%d",&m); 37 nm = (n * m - m - n + 1)<<1;//there are nm nodes in new graph except s and t; 38 int i,j,tmp; 39 memset(head,-1,sizeof(head)); 40 num = 0; 41 42 for(j = 1;j < m;j ++)// 43 { 44 scanf("%d",&tmp); 45 add(j,nm + 1,tmp); 46 } 47 for(i = 1;i < n - 1;i ++) 48 { 49 for(j = 1;j < m;j ++) 50 { 51 scanf("%d",&tmp); 52 add((i<<1)* (m - 1) + j,((i<<1) - 1) * (m - 1) + j,tmp); 53 } 54 } 55 for(j = 1;j < m;j ++) 56 { 57 scanf("%d",&tmp); 58 add(0,((n<<1)-3) * (m - 1) + j,tmp); 59 } 60 61 for(i = 0;i < n - 1;i ++) 62 { 63 for(j = 1;j <= m;j ++) 64 { 65 scanf("%d",&tmp); 66 if(j == 1) 67 add(0,(i<<1)*(m - 1) + m,tmp); 68 else if(j == m) 69 add((i<<1|1)*(m - 1),nm + 1,tmp); 70 else 71 add((i<<1)*(m - 1) + j - 1,(i<<1)*(m - 1) + j + m - 1,tmp); 72 } 73 } 74 75 for(i = 0;i < n - 1;i ++) 76 { 77 for(j = 1;j < m;j ++) 78 { 79 scanf("%d",&tmp); 80 add((i<<1|1)*(m - 1) + j,(i<<1)*(m - 1) + j,tmp); 81 } 82 } 83 } 84 void SPFA() 85 { 86 int i,front,rear; 87 memset(flag,false,sizeof(flag)); 88 memset(dis,0x3f,sizeof(dis)); 89 front = rear = dis[0] = 0; 90 que[rear ++] = 0; 91 flag[0] = true; 92 while(front != rear) 93 { 94 int u = que[front ++]; 95 flag[u] = false; 96 if(front == M) 97 front = 0; 98 for(int i = head[u];~i;i = g[i].next) 99 { 100 int v = g[i].to; 101 if(dis[v] > dis[u] + g[i].val) 102 { 103 dis[v] = dis[u] + g[i].val; 104 if(flag[v] == false) 105 { 106 flag[v] = true; 107 que[rear ++] = v; 108 if(rear == M) 109 rear = 0; 110 } 111 } 112 } 113 } 114 } 115 void solve() 116 { 117 SPFA(); 118 printf("%d\n",dis[nm + 1]); 119 } 120 int main() 121 { 122 while(scanf("%d",&n) != EOF) 123 { 124 build(); 125 solve(); 126 } 127 return 0; 128 }