bzoj 1001 狼抓兔子
题目大意:
一个网格图,路径样式如下
求最小割
思路:
数据太大,不能直接最小割,而这个图是个平面图(显而易见)
于是我们可以对偶图
所谓对偶图,就是把平面图的每个块看做是一个点,如图:
然后spfa跑一遍最短路就好了
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #include<cstdlib>
7 #include<set>
8 #include<map>
9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 1001001
15 #define MOD
16 using namespace std;
17 inline int read()
18 {
19 int x=0,f=1;
20 char ch;ch=getchar();
21 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
22 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
23 return x*f;
24 }
25 int n,m,x,ans,lim;
26 int to[MAXN*6+2010],val[MAXN*6+4010],first[MAXN*2],next[MAXN*6+4010],cnt;
27 int dis[MAXN*2];
28 bool vis[MAXN*2];
29 void add(int u,int v,int d) {next[++cnt]=first[u],first[u]=cnt,val[cnt]=d,to[cnt]=v;}
30 void spfa()
31 {
32 memset(dis,127,sizeof(dis));
33 queue <int> q;
34 q.push(0);dis[0]=0,vis[0]=1;
35 while(!q.empty())
36 {
37 int k=q.front();
38 q.pop();
39 vis[k]=0;
40 for(int i=first[k];i;i=next[i])
41 if(dis[to[i]]>dis[k]+val[i])
42 {
43 dis[to[i]]=dis[k]+val[i];
44 if(!vis[to[i]]) {q.push(to[i]);vis[to[i]]=1;}
45 }
46 }
47 printf("%d",dis[lim+1]);
48 }
49 int main()
50 {
51 n=read(),m=read();
52 ans=inf,lim=2*(m-1)*(n-1);
53 if(n==1)
54 {
55 for(int i=1;i<m;i++) {x=read(),ans=min(ans,x);}
56 printf("%d",ans);return 0;
57 }
58 if(m==1)
59 {
60 for(int i=1;i<n;i++) {x=read(),ans=min(ans,x);}
61 printf("%d",ans);return 0;
62 }
63 for(int i=1;i<=n;i++)
64 {
65 for(int j=1;j<m;j++)
66 {
67 x=read();
68 if(i==1) {add(lim+1,j*2,x);add(j*2,lim+1,x);continue;}
69 if(i==n) {add(0,(n-2)*(m-1)*2+j*2-1,x);add((n-2)*(m-1)*2+j*2-1,0,x);continue;}
70 add((i-1)*(m-1)*2+j*2,(i-2)*(m-1)*2+j*2-1,x);add((i-2)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,x);
71 }
72 }
73 for(int i=1;i<n;i++)
74 {
75 for(int j=1;j<=m;j++)
76 {
77 x=read();
78 if(j==1) {add(0,(m-1)*(i-1)*2+1,x);add(2*(m-1)*(i-1)+1,0,x);continue;}
79 if(j==m) {add(lim+1,i*(m-1)*2,x);add(i*(m-1)*2,lim+1,x);continue;}
80 add((i-1)*(m-1)*2+2*(j-1),(i-1)*(m-1)*2+2*j-1,x);add((i-1)*(m-1)*2+2*j-1,(i-1)*(m-1)*2+2*(j-1),x);
81 }
82 }
83 for(int i=1;i<n;i++)
84 {
85 for(int j=1;j<m;j++)
86 {
87 x=read();
88 add((i-1)*(m-1)*2+2*j,(i-1)*(m-1)*2+2*j-1,x);add((i-1)*(m-1)*2+2*j-1,(i-1)*(m-1)*2+2*j,x);
89 }
90 }
91 spfa();
92 }