【BZOJ1001】狼抓兔子(平面图最小割转最短路)
题意:有一张平面图,求它的最小割。N,M.表示网格的大小,N,M均小于等于1000.
左上角点为(1,1),右下角点为(N,M).有以下三种类型的道路
1:(x,y)<==>(x+1,y)
2:(x,y)<==>(x,y+1)
3:(x,y)<==>(x+1,y+1)
思路:第一眼看就是一个最小割=最大流,但点数1000000,边数6000000过大
所以要平面图最小割转最短路 详情见周驿东《浅析最大最小定理在信息学竞赛中的应用》
n=1和m=1要特判,链状的我也母鸡为什么会错,特判就对了
1 var q:array[0..3100000]of longint; 2 dis,head:array[1..2100000]of longint; 3 inq:array[1..2100000]of boolean; 4 vet,next,len:array[1..6100000]of longint; 5 num:array[1..1100,1..1100,1..2]of longint; 6 n,m,i,j,x,tot,st,ed,s,ans:longint; 7 8 procedure add(a,b,c:longint); 9 begin 10 inc(tot); 11 next[tot]:=head[a]; 12 vet[tot]:=b; 13 len[tot]:=c; 14 head[a]:=tot; 15 end; 16 17 function min(x,y:longint):longint; 18 begin 19 if x<y then exit(x); 20 exit(y); 21 end; 22 23 procedure spfa; 24 var t,w,e,v,u:longint; 25 begin 26 fillchar(dis,sizeof(dis),$1f); 27 fillchar(inq,sizeof(inq),false); 28 t:=-1; w:=0; q[0]:=st; dis[st]:=0; inq[st]:=true; 29 while t<w do 30 begin 31 inc(t); u:=q[t mod (ed+1)]; 32 inq[u]:=false; 33 e:=head[u]; 34 while e<>0 do 35 begin 36 v:=vet[e]; 37 if dis[u]+len[e]<dis[v] then 38 begin 39 dis[v]:=dis[u]+len[e]; 40 if not inq[v] then 41 begin 42 inc(w); q[w mod (ed+1)]:=v; 43 inq[v]:=true; 44 end; 45 end; 46 e:=next[e]; 47 end; 48 end; 49 writeln(dis[ed]); 50 end; 51 52 begin 53 //assign(input,'bzoj1001.in'); reset(input); 54 //assign(output,'bzoj1001.out'); rewrite(output); 55 readln(n,m); 56 if (n=1)and(m=1) then 57 begin 58 writeln(0); 59 exit; 60 end; 61 if n=1 then 62 begin 63 ans:=maxlongint; 64 for i:=1 to m-1 do begin read(x); ans:=min(ans,x); end; 65 writeln(ans); 66 exit; 67 end; 68 if m=1 then 69 begin 70 ans:=maxlongint; 71 for j:=1 to n-1 do begin read(x); ans:=min(ans,x); end; 72 writeln(ans); 73 exit; 74 end; 75 76 for i:=1 to n do 77 for j:=1 to m do 78 begin 79 inc(s); num[i,j,1]:=s; 80 inc(s); num[i,j,2]:=s; 81 end; 82 inc(s); 83 st:=s; ed:=s+1; 84 for i:=1 to n do 85 for j:=1 to m-1 do 86 begin 87 read(x); 88 if i=1 then 89 begin 90 add(st,num[i,j,2],x); 91 add(num[i,j,2],st,x); 92 end 93 else if i=n then 94 begin 95 add(ed,num[i-1,j,1],x); 96 add(num[i-1,j,1],ed,x); 97 end 98 else 99 begin 100 add(num[i-1,j,1],num[i,j,2],x); 101 add(num[i,j,2],num[i-1,j,1],x); 102 end; 103 end; 104 for i:=1 to n-1 do 105 for j:=1 to m do 106 begin 107 read(x); 108 if j=1 then 109 begin 110 add(num[i,j,1],ed,x); 111 add(ed,num[i,j,1],x); 112 end 113 else if j=m then 114 begin 115 add(num[i,j-1,2],st,x); 116 add(st,num[i,j-1,2],x); 117 end 118 else 119 begin 120 add(num[i,j-1,2],num[i,j,1],x); 121 add(num[i,j,1],num[i,j-1,2],x); 122 end; 123 end; 124 for i:=1 to n-1 do 125 for j:=1 to m-1 do 126 begin 127 read(x); 128 add(num[i,j,1],num[i,j,2],x); 129 add(num[i,j,2],num[i,j,1],x); 130 end; 131 spfa; 132 // close(input); 133 //close(output); 134 end.
UPD(2018.10.17):C++
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 #define N 2100000 21 #define M 6100000 22 #define eps 1e-8 23 #define pi acos(-1) 24 #define oo 1e9 25 26 int num[1100][1100][3],q[N],dis[N],head[N],inq[N], 27 vet[M],nxt[M],len[M],tot,s,st,ed; 28 29 int add(int a,int b,int c) 30 { 31 nxt[++tot]=head[a]; 32 vet[tot]=b; 33 len[tot]=c; 34 head[a]=tot; 35 } 36 37 void spfa(int st,int ed) 38 { 39 memset(dis,0x3f,sizeof(dis)); 40 memset(inq,0,sizeof(inq)); 41 int t=0; int w=1; q[1]=st; dis[st]=0; inq[st]=1; 42 while(t<w) 43 { 44 t++; int u=q[t%(s+1)]; 45 inq[u]=0; 46 int e=head[u]; 47 while(e) 48 { 49 int v=vet[e]; 50 if(dis[u]+len[e]<dis[v]) 51 { 52 dis[v]=dis[u]+len[e]; 53 if(!inq[v]) 54 { 55 w++; q[w%(s+1)]=v; 56 inq[v]=1; 57 } 58 } 59 e=nxt[e]; 60 } 61 } 62 printf("%d\n",dis[ed]); 63 } 64 65 int main() 66 { 67 //freopen("bzoj1001.in","r",stdin); 68 //freopen("bzoj1001.out","w",stdout); 69 int n,m; 70 scanf("%d%d",&n,&m); 71 if(n==1&&m==1){printf("0\n"); return 0;} 72 if(n==1) 73 { 74 int ans=oo; 75 for(int i=1;i<m;i++) 76 { 77 int x; 78 scanf("%d",&x); 79 ans=min(ans,x); 80 } 81 printf("%d\n",ans); 82 return 0; 83 } 84 if(m==1) 85 { 86 int ans=oo; 87 for(int i=1;i<n;i++) 88 { 89 int x; 90 scanf("%d",&x); 91 ans=min(ans,x); 92 } 93 printf("%d\n",ans); 94 return 0; 95 } 96 s=0; 97 for(int i=1;i<=n;i++) 98 for(int j=1;j<=m;j++) 99 for(int k=1;k<=2;k++) num[i][j][k]=++s; 100 int st=++s; 101 int ed=++s; 102 for(int i=1;i<=n;i++) 103 for(int j=1;j<=m-1;j++) 104 { 105 int x; 106 scanf("%d",&x); 107 if(i==1) 108 { 109 add(st,num[i][j][2],x); 110 add(num[i][j][2],st,x); 111 } 112 else if(i==n) 113 { 114 add(ed,num[i-1][j][1],x); 115 add(num[i-1][j][1],ed,x); 116 } 117 else 118 { 119 add(num[i-1][j][1],num[i][j][2],x); 120 add(num[i][j][2],num[i-1][j][1],x); 121 } 122 } //横边 123 for(int i=1;i<=n-1;i++) 124 for(int j=1;j<=m;j++) 125 { 126 int x; 127 scanf("%d",&x); 128 if(j==1) 129 { 130 add(num[i][j][1],ed,x); 131 add(ed,num[i][j][1],x); 132 } 133 else if(j==m) 134 { 135 add(num[i][j-1][2],st,x); 136 add(st,num[i][j-1][2],x); 137 } 138 else 139 { 140 add(num[i][j-1][2],num[i][j][1],x); 141 add(num[i][j][1],num[i][j-1][2],x); 142 } 143 } //纵边 144 145 for(int i=1;i<=n-1;i++) 146 for(int j=1;j<=m-1;j++) 147 { 148 int x; 149 scanf("%d",&x); 150 add(num[i][j][1],num[i][j][2],x); 151 add(num[i][j][2],num[i][j][1],x); 152 } //斜边 153 spfa(st,ed); 154 return 0; 155 }
null