BZOJ1001 狼抓兔子 终于过了!

    时间来不及了,先贴代码吧!有时间再写。

   好苦逼啊,WA了若干次,还有一次RE,一次TLE。

   虽然主要运用的算法和资料都由师兄提供了。还是太弱了,太天真了。

   首先,数据范围就WA了,RE了,TLE了。

   然后构图上有bug。最后还是仿着师兄的把构图重新写了。加油吧!

  这道题的主要思路首先应该是网络流中的最小割,但由于数据范围太大,直接用最小割的算法会TLE,而且没有正确地利用题目特征,这道题的图是个S-T图,我们可以建出原图的对偶图,然后跑一次dijkstra()。详情请参考《浅析最大最小定理在信息学竞赛中的应用》。

   一个网格图中求最小割,很特殊的是这个图是一个平面图,最小割=最大流=对偶图中最短路(平面图)。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<queue>
  4 #include<cstring>
  5 #define maxn 2100009
  6 #define rep(i,j,k) for(int i = j; i <= k; i++)
  7 using namespace std;
  8 
  9 int read()
 10 {
 11     int s = 0, t = 1; char c = getchar();
 12     while( !isdigit(c) ) {
 13         if( c == '-' ) t = -1; c = getchar();
 14     }
 15     while( isdigit(c) ){
 16         s = s * 10 + c - '0'; c = getchar();
 17     } 
 18     return s * t;
 19 }
 20 
 21 int d[maxn], n, m, sx, tx;
 22 bool done[maxn] = {0}; 
 23 
 24 struct node{
 25 int d, u;
 26 bool operator < (const node& rhs) const{
 27         return d > rhs.d;
 28      }
 29 };
 30 
 31 struct edge{
 32 int to, key;
 33 edge* next;
 34 };
 35 
 36 edge *pt, edges[maxn*3], *head[maxn];
 37 
 38 void add_edge(int x,int y,int val){
 39    pt->to = y;pt->key = val;
 40    pt->next = head[x];
 41    head[x] = pt++;
 42    pt->to = x, pt->key= val;
 43    pt->next = head[y];
 44    head[y] = pt++; 
 45 }
 46 priority_queue<node> Q;
 47 
 48 void dijkstra()
 49 {
 50      memset(d,127,sizeof(d));
 51      d[sx] = 0;
 52      Q.push((node){0,sx});
 53      while( !Q.empty() ){
 54         node x = Q.top(); Q.pop();
 55         int u = x.u;
 56         if( done[u] ) continue;
 57         done[u] = 1;
 58         for( edge*i = head[u]; i ; i = i->next ){
 59             int y = i->to, key = i->key;
 60             if( d[y] > d[u]+key ) {
 61                 d[y] = d[u]+key;
 62                 Q.push((node){d[y],y});
 63             }
 64         }
 65      }
 66 }
 67 
 68 int main()
 69 {
 70     //freopen("out.txt","w",stdout);
 71    pt = edges;
 72    n = read(), m = read(); 
 73    sx = 0, tx = (n-1)*(m-1) * 2+ 1;
 74    rep(i,0,n-1) {
 75       int xx = (2*m-2)*i;
 76       int xy = (2*m-2)*(i-1);
 77       rep(j,1,m-1){
 78          int x = read();
 79          if( !i ) {
 80             add_edge(xx+2*j,tx,x);
 81             //cout<<tx<<" "<<xx+2*j+1<<" "<<x<<endl;
 82          } 
 83          else if( i == n-1 ) {
 84             add_edge(sx,xy+2*j-1,x);
 85             //cout<<xy+2*j<<" "<<sx<<" "<<x<<endl;
 86          }
 87          else{
 88             add_edge(xx+2*j,xy+2*j-1,x);
 89             //cout<<xy+2*j<<" "<<xx+2*j+1<<" "<<x<<endl;
 90          }
 91       }
 92    }
 93    rep(i,0,n-2){
 94       int xx = 2*(m-1)*(i);
 95       rep(j,1,m){
 96          int x = read();
 97          if( j == 1 ){
 98             add_edge(sx,xx+2*j-1,x);
 99             //cout<<sx<<" "<<xx<<" "<<x<<endl;
100          } 
101          else if( j == m ){
102             add_edge(tx,xx+2*j-2,x);
103             //cout<<tx<<" "<<xx+2*j-1<<" "<<x<<endl;
104          }
105          else {
106             add_edge(xx+2*j-2,xx+2*j-1,x);
107             //cout<<xx+2*j<<" "<<xx+2*j-1<<" "<<x<<endl;
108          }
109       }
110    }
111    rep(i,0,n-2){
112      int xx = 2*(m-1)*(i); 
113      rep(j,1,m-1){
114         int x = read();
115         add_edge(xx+2*j,xx+2*j-1,x);
116         //cout<<xx+2*j<<" "<<xx+2*j+1<<" "<<endl;
117      }
118    }
119    dijkstra();
120    cout<<d[tx]<<endl;
121    return 0;
122 }

    不过,也想请大神把我指出下面这份代码错哪了?

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<queue>
  4 #include<cstring>
  5 #define maxn 2100009
  6 #define sx   2100000
  7 #define tx   2100001
  8 #define rep(i,j,k) for(int i = j; i <= k; i++)
  9 using namespace std;
 10  
 11 int read()
 12 {
 13     int s = 0, t = 1; char c = getchar();
 14     while( !isdigit(c) ) {
 15         if( c == '-' ) t = -1; c = getchar();
 16     }
 17     while( isdigit(c) ){
 18         s = s * 10 + c - '0'; c = getchar();
 19     } 
 20     return s * t;
 21 }
 22  
 23 int d[maxn], n, m;
 24 bool done[maxn] = {0}; 
 25  
 26 struct node{
 27 int d, u;
 28 bool operator < (const node& rhs) const{
 29         return d > rhs.d;
 30      }
 31 };
 32  
 33 struct edge{
 34 int to, key;
 35 edge* next;
 36 };
 37  
 38 edge *pt, edges[maxn*3], *head[maxn];
 39  
 40 void add_edge(int x,int y,int val){
 41    pt->to = y;pt->key = val;
 42    pt->next = head[x];
 43    head[x] = pt++;
 44    pt->to = x, pt->key= val;
 45    pt->next = head[y];
 46    head[y] = pt++; 
 47 }
 48 priority_queue<node> Q;
 49  
 50 void dijkstra()
 51 {
 52      memset(d,127,sizeof(d));
 53      d[sx] = 0;
 54      Q.push((node){0,sx});
 55      while( !Q.empty() ){
 56         node x = Q.top(); Q.pop();
 57         int u = x.u;
 58         if( done[u] ) continue;
 59         done[u] = 1;
 60         for( edge*i = head[u]; i ; i = i->next ){
 61             int y = i->to, key = i->key;
 62             if( d[y] > d[u]+key ) {
 63                 d[y] = d[u]+key;
 64                 Q.push((node){d[y],y});
 65             }
 66         }
 67      }
 68 }
 69  
 70 int main()
 71 {
 72     //freopen("out.txt","w",stdout);
 73    pt = edges;
 74    n = read(), m = read(); 
 75    rep(i,0,n-1) {
 76       int xx = (2*m-2)*i;
 77       int xy = (2*m-2)*(i-1);
 78       rep(j,0,m-2){
 79          int x = read();
 80          if( !i ) {
 81             add_edge(xx+2*j+1,tx,x);
 82             //cout<<tx<<" "<<xx+2*j+1<<" "<<x<<endl;
 83          } 
 84          else if( i == n-1 ) {
 85             add_edge(sx,xy+2*j,x);
 86             //cout<<xy+2*j<<" "<<sx<<" "<<x<<endl;
 87          }
 88          else{
 89             add_edge(xx+2*j+1,xy+2*j,x);
 90             //cout<<xy+2*j<<" "<<xx+2*j+1<<" "<<x<<endl;
 91          }
 92       }
 93    }
 94    rep(i,0,n-2){
 95       int xx = 2*(m-1)*(i);
 96       rep(j,0,m-1){
 97          int x = read();
 98          if( !j ){
 99             add_edge(sx,xx,x);
100             //cout<<sx<<" "<<xx<<" "<<x<<endl;
101          } 
102          else if( j == m-1 ){
103             add_edge(tx,xx+2*j-1,x);
104             //cout<<tx<<" "<<xx+2*j-1<<" "<<x<<endl;
105          }
106          else {
107             add_edge(xx+2*j,xx+2*j-1,x);
108             //cout<<xx+2*j<<" "<<xx+2*j-1<<" "<<x<<endl;
109          }
110       }
111    }
112    rep(i,0,n-2){
113      int xx = 2*(m-1)*(i); 
114      rep(j,0,m-2){
115         int x = read();
116         add_edge(xx+2*j,xx+2*j+1,x);
117         //cout<<xx+2*j<<" "<<xx+2*j+1<<" "<<endl;
118      }
119    }
120    dijkstra();
121    cout<<d[tx]<<endl;
122    return 0;
123 }

 

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 14595  Solved: 3490
[Submit][Status][Discuss]

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

posted on 2015-12-14 18:27  83131  阅读(164)  评论(0编辑  收藏  举报

导航