zoukankan      html  css  js  c++  java
  • bzoj1001题解

    【解题思路】

      显然,这题的答案是这个网格图的最小割。根据最大流-最小割定理,我们可以用网络流算法来求其最小割,时间复杂度最小为O(V2√E)。

      特殊的,这个网格图是一个平面图,于是可以根据平面图最小割-最短路定理,转化为其对偶图的最短路,时间复杂度最小为O(kE)或O(Vlog2V)(民科算法spfa前途不可估量)。

    【参考代码】

      恩,听说这题我当初RE得生活不能自理,于是直接贴了orz::hzwer大神的代码。。

      贴个T掉的SAP板子。。(已修正了假板子的当前弧优化。。但还是T得生活不能自理。。)

      1 #pragma GCC optimize(2)
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <functional>
      5 #define REP(i,low,high) for(register int i=(low);i<=(high);++i)
      6 #define INF (0x7f7f7f7f)
      7 #define function(type) __attribute__((optimize("-O2"))) inline type
      8 #define procedure __attribute__((optimize("-O2"))) inline void
      9 using namespace std;
     10 
     11 //ex_cmp {
     12 template<typename T,class Compare>
     13 inline bool getcmp(T&target,const T&pattern,Compare comp)
     14 {
     15     return comp(pattern,target)?target=pattern,1:0;
     16 }
     17 //} ex_cmp
     18 
     19 //quick_io {
     20 #include <cctype>
     21 #include <cstdio>
     22 function(int) getint()
     23 {
     24     char c=getchar(); for(;!isdigit(c)&&c!='-';c=getchar());
     25     short s=1; for(;c=='-';c=getchar()) s*=-1; int r=0;
     26     for(;isdigit(c);c=getchar()) r=(r<<3)+(r<<1)+c-'0';
     27     return s*r;
     28 }
     29 //} quick_io
     30 
     31 static const int N=1000000,M=3000000; static int cardE=0;
     32 
     33 struct edge
     34 {
     35     int fr,to,cap;
     36     edge(const int&f=0,const int&t=0,const int&c=0)
     37     :fr(f),to(t),cap(c) {}
     38 }edg[(M<<1)+5];
     39 
     40 int hed[N+5],nxt[(M<<1)+5],hsh[1005][1005];
     41 
     42 procedure add_edge(const int&fr,const int&to,const int&cp)
     43 {
     44     edg[cardE]=edge(fr,to,cp),nxt[cardE]=hed[fr],hed[fr]=cardE++;
     45 }
     46 
     47 //SAP {
     48 int aug[N+5],cur[N+5],dis[N+5],gap[N+5],path[N+5];
     49 
     50 function(int) augment(const int&S,const int&T)
     51 {
     52     for(register int i=T;i!=S;i=edg[path[i]].fr)
     53     {
     54         edg[path[i]].cap-=aug[T],edg[path[i]^1].cap+=aug[T];
     55     }
     56     return aug[T];
     57 }
     58 
     59 function(int) SAP(const int&S,const int&T,const int&N)
     60 {
     61     memset(aug,0,sizeof aug),memset(gap,0,sizeof gap);
     62     memset(dis,0,sizeof dis); REP(i,1,N) cur[i]=hed[i];
     63     aug[S]=INF,gap[0]=N; int ret=0;
     64     for(register int fr=S;dis[S]<N;)
     65     {
     66         if(fr==T) ret+=augment(fr=S,T); bool flag=1;
     67         for(register int i=cur[fr];~i;i=nxt[i])
     68         {
     69             int to=edg[i].to;
     70             if(edg[i].cap&&dis[fr]==dis[to]+1)
     71             {
     72                 aug[to]=min(aug[fr],edg[i].cap)
     73                 ,path[to]=cur[fr]=i,fr=to,flag=0; break;
     74             }
     75         }
     76         if(flag)
     77         {
     78             if(!--gap[dis[fr]]) break; dis[fr]=N;
     79             for(register int i=hed[fr];~i;i=nxt[i])
     80             if(edg[i].cap)
     81             {
     82                 getcmp(dis[fr],dis[edg[i].to]+1,less<int>());
     83             }
     84             ++gap[dis[fr]],cur[fr]=hed[fr];
     85             if(fr!=S) fr=edg[path[fr]].fr;
     86         }
     87     }
     88     return ret;
     89 }
     90 //} SAP
     91 
     92 int main()
     93 {
     94     int n=getint(),m=getint(),cardP=0;
     95     REP(i,1,n) REP(j,1,m) hsh[i][j]=++cardP;
     96     memset(hed,-1,sizeof hed),memset(nxt,-1,sizeof nxt);
     97     REP(i,1,n) REP(j,2,m)
     98     {
     99         int w=getint();
    100         add_edge(hsh[i][j-1],hsh[i][j],w),
    101         add_edge(hsh[i][j],hsh[i][j-1],w);
    102     }
    103     REP(i,2,n) REP(j,1,m)
    104     {
    105         int w=getint();
    106         add_edge(hsh[i-1][j],hsh[i][j],w),
    107         add_edge(hsh[i][j],hsh[i-1][j],w);
    108     }
    109     REP(i,2,n) REP(j,2,m)
    110     {
    111         int w=getint();
    112         add_edge(hsh[i-1][j-1],hsh[i][j],w),
    113         add_edge(hsh[i][j],hsh[i-1][j-1],w);
    114     }
    115     printf("%d
    ",SAP(1,cardP,cardP));
    116     return 0;
    117 }
    View Code

      然后对偶图最短路。。(被队列长度卡了好久。。用了循环队列才过。。)

      1 #pragma GCC optimize(2)
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <functional>
      5 #define REP(i,low,high) for(register int i=(low);i<=(high);++i)
      6 #define INF (0x3f3f3f3f)
      7 #define function(type) __attribute__((optimize("-O2"))) inline type
      8 #define procedure __attribute__((optimize("-O2"))) inline void
      9 using namespace std;
     10 
     11 //ex_cmp {
     12 template<typename T,class Compare>
     13 inline bool getcmp(T&target,const T&pattern,Compare comp)
     14 {
     15     return comp(pattern,target)?target=pattern,1:0;
     16 }
     17 //} ex_cmp
     18 
     19 //quick_io {
     20 #include <cctype>
     21 #include <cstdio>
     22 function(long long) getint()
     23 {
     24     char c=getchar(); for(;!isdigit(c)&&c!='+'&&c!='-';c=getchar());
     25     short s=1; for(;c=='+'||c=='-';c=getchar()) if(c=='-') s*=-1;
     26     long long r=0; for(;isdigit(c);c=getchar()) r=(r<<3)+(r<<1)+c-'0';
     27     return s*r;
     28 }
     29 //} quick_io
     30 
     31 static const int N=2000000,M=3000000,SIZE=(N<<1)+10;
     32 
     33 struct edge
     34 {
     35     int to,cap; edge(const int&t=0,const int&c=0):to(t),cap(c) {}
     36 }edg[(M<<1)+10];
     37 
     38 static int cardE=0; int hed[N+10],nxt[(M<<1)+10];
     39 
     40 procedure add_edge(const int&fr,const int&to,const int&cp)
     41 {
     42     edg[++cardE]=edge(to,cp),nxt[cardE]=hed[fr],hed[fr]=cardE;
     43 }
     44 
     45 //SPFA {
     46 bool inq[N+10]={0}; int dis[N+10]={0},q[SIZE];
     47 
     48 function(int&) move(int&n) {return ++n==SIZE?n=0:n;}
     49 
     50 function(int) SPFA(const int&S,const int&T)
     51 {
     52     memset(dis,0x3f,sizeof dis),inq[q[dis[S]=0]=S]=1;
     53     for(register int head=-1,tail=0;head!=tail;)
     54     {
     55         int fr=q[move(head)];
     56         for(register int i=hed[fr];i;i=nxt[i])
     57         {
     58             int to=edg[i].to;
     59             if(
     60                 getcmp(dis[to],dis[fr]+edg[i].cap,less<int>())
     61                 &&!inq[to]
     62             ) inq[q[move(tail)]=to]=1;
     63         }
     64         inq[fr]=0;
     65     }
     66     return dis[T];
     67 }
     68 //} SPFA
     69  
     70 int main()
     71 {
     72     int n=getint(),m=getint(),nm=(n-1)*(m-1)<<1;
     73     if(n==1||m==1)
     74     {
     75         int ans=INF;
     76         REP(i,1,max(m,n)-1) getcmp(ans,(int)getint(),less<int>());
     77         return printf("%d
    ",ans),0;
     78     }
     79     REP(i,1,m-1)
     80     {
     81         int w=getint(); add_edge(i,nm+1,w),add_edge(nm+1,i,w);
     82     }
     83     REP(i,1,n-2) REP(j,1,m-1)
     84     {
     85         int w=getint(),fr=(i<<1)*(m-1)+j,to=fr-m+1;
     86         add_edge(fr,to,w),add_edge(to,fr,w);
     87     }
     88     REP(i,1,m-1)
     89     {
     90         int w=getint(),tmp=((n<<1)-3)*(m-1)+i;
     91         add_edge(0,tmp,w),add_edge(tmp,0,w);
     92     }
     93     REP(i,0,n-2)
     94     {
     95         int w=getint(),tmp=(i<<1)*(m-1)+m;
     96         add_edge(0,tmp,w),add_edge(tmp,0,w);
     97         REP(j,2,m-1)
     98         {
     99             int fr=(i<<1)*(m-1)+j-1,to=fr+m;
    100             add_edge(fr,to,w=getint()),add_edge(to,fr,w);
    101         }
    102         tmp=(m-1)*(i<<1|1),w=getint(),
    103         add_edge(tmp,nm+1,w),add_edge(nm+1,tmp,w);
    104     }
    105     REP(i,0,n-2) REP(j,1,m-1)
    106     {
    107         int w=getint(),fr=(i<<1)*(m-1)+j,to=fr+m-1;
    108         add_edge(fr,to,w),add_edge(to,fr,w);
    109     }
    110     printf("%d
    ",SPFA(0,nm+1));
    111     return 0;
    112 }
    View Code
    We Secure, We Contain, We Protect.
  • 相关阅读:
    UPC12617 卡片
    mcmf的dijkstra板子(来自PHY学长)
    UPC9630 Mad Veterinarian
    UPC8173【 哈希和哈希表】Three Friends
    UPC9655 Plug It In!
    UPC8428 网格VI
    UPC4248【数论】数字迷阵
    UPC4247【数论】普通递归关系
    SPOJ
    hdu 5992 Finding Hotels (kdTree)
  • 原文地址:https://www.cnblogs.com/spactim/p/6273212.html
Copyright © 2011-2022 走看看