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 }
View Code

 

posted @ 2014-01-05 19:14  乌拉拉979  阅读(232)  评论(0编辑  收藏  举报