BZOJ 1001 [BeiJing2006] 狼抓兔子(平面圖最大流)

 

題目大意

 

如今小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子仍是比較在行的。並且如今的兔子還比較笨,它們只有兩個窩,如今你作爲狼王,面對下面這樣一個網格的地形:php

左上角點爲 (1, 1),右下角點爲 (N, M) (上圖中N=4, M=4)。有如下三種類型的道路html

  1: (x, y) <==> (x+1, y)ios

  2: (x, y) <==> (x, y+1)網絡

  3: (x, y) <==> (x+1, y+1)ide

道路上的權值表示這條路上最多可以經過的兔子數,道路是無向的. 左上角和右下角爲兔子的兩個窩,開始時全部的兔子都彙集在左上角 (1, 1) 的窩裏,如今它們要跑到右下角 (N, M) 的窩中去,狼王開始伏擊這些兔子。固然爲了保險起見,若是一條道路上最多經過的兔子數爲 K,狼王須要安排一樣數量的 K 只狼,才能徹底封鎖這條道路,你須要幫助狼王安排一個伏擊方案,使得在將兔子一網打盡的前提下,參與的狼的數量要最小。由於狼還要去找喜羊羊麻煩。優化

 

N, M 均小於等於 1000spa

 

作法分析

 

一看就是最小割問題,寫的比較好的網絡流能夠直接暴力的搞過去,固然,正解確定不是這樣,雖然是一個水題,不過仍是值得一作的code

 

這題須要利用平面圖的對偶圖性質htm

平面圖的對偶圖很好構造:blog

  將原圖中的面變成新圖中的點

  原圖中,每條邊一定分割了兩個面,在新圖中,對應的點之間添加一條邊,邊權仍是原圖中邊的邊權

 

在原圖中的一個全局的割就對應了新圖中的一個環,也就是說,若是想要求原圖中的一個全局最小割,只須要在新圖中找一個最小環便可

 

怎麼求出原圖中分割固定點 s 和 t(s 和 t 處於一個無線大的平面的邊緣) 的一個最小割呢?

  先在原圖中添加 s 到 t 的邊,給原圖增長了一個面

  構造原圖的對偶圖,把因爲增邊而增長的新面對應的點設爲 S,無窮大的平面對應的點設爲 T

  刪掉對偶圖中 S 到 T 直接相連的邊

  求出 S 到 T 的最短路就能夠了

詳細請看周冬的論文 《兩極相通——淺析最大—最小定理在信息學競賽中的應用》

 

這題按照上面將的建圖,跑最短路就好了,據說 SPFA 也能過,我沒試過,用的堆優化的 Dijkstra + 輸入外掛直接 516ms 過掉

 

參考代碼

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 
  6 using namespace std;
  7 
  8 const int N=2000006, INF=0x3fffffff, E=N*3;
  9 
 10 struct ARC {
 11     int u, val, next;
 12     inline void init(int a, int b, int c) {
 13         u=a, val=b, next=c;
 14     }
 15 } arc[E];
 16 int head[N], tot, S, T, n, m, dis[N];
 17 bool vs[N];
 18 
 19 struct data {
 20     int u, dis;
 21     data() {}
 22     data(int a, int b) : u(a), dis(b) {}
 23     bool operator < (const data &T) const {
 24         return dis>T.dis;
 25     }
 26 };
 27 
 28 inline void add_arc(int s, int t, int val) {
 29     arc[tot].init(t, val, head[s]);
 30     head[s]=tot++;
 31 }
 32 
 33 priority_queue <data> Q;
 34 void Dijkstra() {
 35     fill(dis, dis+T+1, INF);
 36     fill(vs, vs+T+1, 0);
 37     while(!Q.empty()) Q.pop();
 38     dis[S]=0, Q.push(data(S, 0));
 39     for(int u; !Q.empty(); ) {
 40         u=Q.top().u, Q.pop();
 41         if(vs[u]) continue;
 42         if(u==T) {
 43             printf("%d\n", dis[T]);
 44             break;
 45         }
 46         vs[u]=1;
 47         for(int e=head[u]; e!=-1; e=arc[e].next) {
 48             int v=arc[e].u;
 49             if(vs[v] || dis[u]+arc[e].val>=dis[v]) continue;
 50             dis[v]=dis[u]+arc[e].val;
 51             Q.push(data(v, dis[v]));
 52         }
 53     }
 54 }
 55 
 56 void read(int &x) {
 57     char c;
 58     while((c=getchar())<'0' || c>'9');
 59     x=c-'0';
 60     while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 61 }
 62 
 63 void Input() {
 64     for(int i=0, id1, id2, a; i<=n-1; i++)
 65         for(int j=1; j<=m-1; j++) {
 66             read(a);
 67             id1=((i-1)*(m-1)+j)*2-1;
 68             id2=(i*(m-1)+j)*2;
 69             if(i==0) id1=T;
 70             else if(i==n-1) id2=S;
 71             add_arc(id1, id2, a);
 72             add_arc(id2, id1, a);
 73         }
 74 
 75     for(int i=1, id1, id2, a; i<=n-1; i++)
 76         for(int j=0; j<m; j++) {
 77             read(a);
 78             id1=((i-1)*(m-1)+j)*2;
 79             id2=((i-1)*(m-1)+j+1)*2-1;
 80             if(j==0) id1=S;
 81             else if(j==m-1) id2=T;
 82             add_arc(id1, id2, a);
 83             add_arc(id2, id1, a);
 84         }
 85 
 86     for(int i=1, id1, id2, a; i<=n-1; i++)
 87         for(int j=1; j<=m-1; j++) {
 88             read(a);
 89             id1=((i-1)*(m-1)+j)*2;
 90             id2=((i-1)*(m-1)+j)*2-1;
 91             add_arc(id1, id2, a);
 92             add_arc(id2, id1, a);
 93         }
 94 }
 95 
 96 int main() {
 97     read(n), read(m);
 98     S=0, T=(n-1)*(m-1)*2+1;
 99     fill(head, head+T+1, -1), tot=0;
100     if(n==1 || m==1) {
101         if(n>m) swap(n, m);
102         int ans=INF;
103         for(int i=1, a; i<m; i++) {
104             read(a);
105             if(ans>a) ans=a;
106         }
107         printf("%d\n", ans==INF?0:ans);
108     }
109     else Input(), Dijkstra();
110     return 0;
111 }
BZOJ 1001

 

題目連接 & AC 通道

 

BZOJ 1001 [BeiJing2006] 狼抓兔子

相關文章
相關標籤/搜索