【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 }

 

posted on 2016-12-02 14:34  myx12345  阅读(260)  评论(0编辑  收藏  举报

导航