# BZOJ1001 [BeiJing2006]狼抓兔子 平面图转对偶图，最小割转最短路

## 1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 28885  Solved: 7540
[Submit][Status][Discuss]

## Description

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

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

## Sample Output

14

很容易可以看出这是一道求最小割的题，但图太大了网络流没法跑。网上有人网络流水过的，但我写的网络流莫名奇妙一直WA...

  1 /**************************************************************
2     Problem: 1001
3     User: mizersy
4     Language: C++
6 ****************************************************************/
7
8 #include <bits/stdc++.h>
9 using namespace std;
10 const int MAXN = 2000010;
11 const int MAXM = 6200010;
12 const int INF = 0x3f3f3f3f;
13 struct Edge{
14     int to,next,cap,flow;
15 } edge[MAXM];
16 int tol;
18 void init(){
19     tol = 2;
21 }
22 void addedge(int u,int v,int w,int rw = 0){
23     edge[tol].to = v;
24     edge[tol].cap = w;
25     edge[tol].flow = 0;
28     edge[tol].to = u;
29     edge[tol].cap = rw;
30     edge[tol].flow = 0;
33 }
34 int Q[MAXN];
35 int dep[MAXN],cur[MAXN],sta[MAXN];
36 bool bfs(int s,int t,int n){
37     int front = 0,tail = 0;
38     memset(dep,-1,sizeof(dep[0])*(n+1));
39     dep[s] = 0;
40     Q[tail++] = s;
41     while(front < tail){
42         int u = Q[front++];
43         for(int i = head[u]; i !=-1; i = edge[i].next){
44             int v = edge[i].to;
45             if(edge[i].cap > edge[i].flow && dep[v] ==-1){
46                 dep[v] = dep[u] + 1;
47                 if(v == t)
48                     return true;
49                 Q[tail++] = v;
50             }
51         }
52     }
53     return false;
54 }
55 int dinic(int s,int t,int n){
56     int maxflow = 0;
57     while(bfs(s,t,n)){
58         for(int i = 0; i <= n; i++) cur[i] = head[i];
59         int u = s, tail = 0;
60         while(cur[s] !=-1){
61             if(u == t){
62                 int tp = INF;
63                 for(int i = tail-1; i >= 0; i--)
64                     tp = min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
65                 maxflow += tp;
66                 for(int i = tail-1; i >= 0; i--){
67                     edge[sta[i]].flow += tp;
68                     edge[sta[i]^1].flow-= tp;
69                     if(edge[sta[i]].cap-edge[sta[i]].flow == 0)
70                         tail = i;
71                 }
72                 u = edge[sta[tail]^1].to;
73             }else if(cur[u] !=-1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to])
74             {
75                 sta[tail++] = cur[u];
76                 u = edge[cur[u]].to;
77             }else{
78                 while(u != s && cur[u] ==-1)
79                     u = edge[sta[--tail]^1].to;
80                 cur[u] = edge[cur[u]].next;
81             }
82         }
83     }
84     return maxflow;
85 }
86 int n,m,cnt;
87 int a[1005][1005];
88
89 int point(int i,int j){
90     return (i-1)*m+j;
91 }
92
93 int main(){
94     scanf("%d%d",&n,&m);
95     cnt = 0;
96     init();
97     memset(a,0,sizeof(a));
98     for (int i = 1;i <= n;++i){
99         for (int j = 1;j < m;++j){
100             int w; scanf("%d",&w);
102         }
103     }
104     for (int i = 1;i < n;++i){
105         for (int j = 1;j <= m;++j){
106             int w; scanf("%d",&w);
108         }
109     }
110     for (int i = 1;i < n;++i){
111         for (int j = 1;j < m;++j){
112             int w; scanf("%d",&w);
114         }
115     }
116     printf("%d\n",dinic(1,n*m,n*m));
117 }
View Code

  1 /**************************************************************
2     Problem: 1001
3     User: mizersy
4     Language: C++
5     Result: Accepted
6     Time:3108 ms
7     Memory:118480 kb
8 ****************************************************************/
9
10 #include <bits/stdc++.h>
11 using namespace std;
12 const int MAXN = 2000005;
13 struct Edge{int to,next,w;}edge[MAXN*4];
14 int tol,n,m,w;
16 void init(){
17     tol = 0;
18     memset(vis,0,sizeof(vis));
19     memset(dis,0x3f3f3f3f,sizeof(dis));
21 }
22
23 void addedge(int u,int v,int w){
28 }
29
30 void getmap(){
31     for (int j = 1;j < m;++j){
32         scanf("%d",&w);
34     }
35     for (int i = 2;i < n;++i){
36         for (int j = 1;j < m;++j){
37             scanf("%d",&w);
39         }
40     }
41     if (n >= 2)
42     for (int j = 1;j < m;++j){
43         scanf("%d",&w);
45     }
46     for (int i = 1;i < n;++i){
47         for (int j = 1;j <= m;++j){
48             scanf("%d",&w);
49             if (j == 1) addedge(2*(n-1)*(m-1)+1,2*(i-1)*(m-1)+1,w);
50             else if (j == m) addedge(2*i*(m-1),0,w);
52         }
53     }
54
55     for (int i = 1;i < n;++i){
56         for (int j = 1;j < m;++j){
57             scanf("%d",&w);
59         }
60     }
61 }
62
63 int spfa(int s,int t){
64     queue <int> q;
65     dis[s] = 0; vis[s] = 1;
66     q.push(s);
67     while(!q.empty()){
68         int u = q.front(); q.pop();
69         vis[u] = 0;
70         for (int i = head[u];i != -1;i = edge[i].next){
71             int v = edge[i].to,w = edge[i].w;
72             if (dis[v] > dis[u] + w){
73                 dis[v] = dis[u] + w;
74                 if (!vis[v]){
75                     vis[v] = 1;
76                     q.push(v);
77                 }
78             }
79         }
80     }
81     return dis[t];
82 }
83
84 int main(){
85     init();
86     scanf("%d%d",&n,&m);
87     if (n == 1 || m == 1){
88         if (n > m) swap(n,m);
89         int ans = 0x3f3f3f3f;
90         for (int i = 1;i < m;++i){
91             scanf("%d",&w);
92             ans = min(ans,w);
93         }
94         if (ans == 0x3f3f3f3f) ans = 0;
95         printf("%d\n",ans);
96         return 0;
97     }
98     getmap();
99     printf("%d\n",spfa(0,2*(m-1)*(n-1)+1));
100     return 0;
101 }

• 0
点赞
• 0
收藏
• 0
评论
10-06 95
11-17 81
02-24 1401
04-17 655
09-14 408
05-13 44
06-28 459
07-17 34
12-09
12-09

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助