zoukankan      html  css  js  c++  java
  • [bzoj1001][BeiJing2006]狼抓兔子-题解[平面图最小割转最短路]/[Dinic求最小割]

    Description

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
    而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

     如果图片挂了请通知博主

    左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 
    1:(x,y)<==>(x+1,y) 
    2:(x,y)<==>(x,y+1) 
    3:(x,y)<==>(x+1,y+1) 
    道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
    开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
    这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
    才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
    狼的数量要最小。因为狼还要去找喜羊羊麻烦.

    Input

    第一行为N,M.表示网格的大小,N,M均小于等于1000.
    接下来分三部分
    第一部分共N行,每行M-1个数,表示横向道路的权值. 
    第二部分共N-1行,每行M个数,表示纵向道路的权值. 
    第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 
    输入文件保证不超过10M

    Output

    输出一个整数,表示参与伏击的狼的最小数量.

    Sample Input

    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

     


    算是接触网络流做的第一道题吧。。这道题是可以用Dinic做的,而且跑的挺快,也可以用平面图最小割转最短路。

    我觉得会Dinic的也稍微看看这个东西吧,多了解一点东西总是好的 。

    这个平面图最小割转最短路不了解的可以去看周冬的论文

    将平面图转成对偶图以后求最短路就行了。

    如果没看懂的话可以暂且看看我这里的解释。。(但务必要看!)

    如果图片挂了请通知博主

     在你构造对偶图的时候,你会发现,你不知道外面的那个面属于源点还是汇点。

    就像这张图,我们把每一条边都构造出与其对偶的一条边,作一条源点到汇点的对角线(这条线并不是一条边),然后将整个对偶图分为两面,一面作为源点,另一面为汇点。

    每一条边相当于拦截原图的一条对应边,因此从对偶图源点到汇点的一条路径就对应一条割。

    所以我们使每一条对偶图的边的权值都等于对应边的权值,这样得到的最短路就是最小割了。

    啊。。就是这样啦。。接下来上代码。。(我最短路写的很丑。。)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<queue>
      6 #define N 1000
      7 #define M 1000
      8 #define mod N*M
      9 #define Max 2147483647
     10 #define ll long long
     11 #define l(A,B) ((A-1)*m+B)
     12 using namespace std;
     13 struct edge
     14 {
     15     int to;
     16     int next;
     17     int dis;
     18 }mp[((N-1)*M+(M-1)*N+(N-1)*(M-1))*2];
     19 int n,m,h,head[N*M+5],que[N*M+5],tip,hd,tl,ans,s,t;
     20 ll tim=1,user[N*M+5];
     21 int read()
     22 {
     23     char ch=getchar();int kin=1,gi=0;
     24     while(ch>'9'||ch<'0'){if(ch=='-')kin=-1;ch=getchar();}
     25     while(ch>='0'&&ch<='9'){gi=gi*10+ch-48;ch=getchar();}
     26     return kin*gi;
     27 }
     28 void add(int u,int v,int dis)
     29 {
     30     mp[++h].dis=dis;
     31     mp[h].to=v;
     32     mp[h].next=head[u];
     33     head[u]=h;
     34 }
     35 void init()
     36 {
     37     int k;
     38     for(int i=1;i<=n;++i)
     39     for(int j=1;j<m;++j)
     40     {
     41         k=read();
     42         add(l(i,j),l(i,j+1),k);
     43         add(l(i,j+1),l(i,j),k);
     44     }
     45     for(int i=1;i<n;++i)
     46     for(int j=1;j<=m;++j)
     47     {
     48         k=read();
     49         add(l(i,j),l(i+1,j),k);
     50         add(l(i+1,j),l(i,j),k);
     51     }
     52     for(int i=1;i<n;++i)
     53     for(int j=1;j<m;++j)
     54     {
     55         k=read();
     56         add(l(i,j),l(i+1,j+1),k);
     57         add(l(i+1,j+1),l(i,j),k);
     58     }
     59 }
     60 int bfs()
     61 {
     62     int nw;
     63     tl=0;hd=0;
     64     tip=user[s]=tim;que[tl++]=s;tl%=mod;
     65     while(tl!=hd)
     66     {
     67         nw=que[hd++];hd%=mod;
     68         for(int i=head[nw];i;i=mp[i].next)
     69         {
     70             if(user[mp[i].to]<tim&&mp[i].dis>0)
     71             {
     72                 user[mp[i].to]=user[nw]+1;
     73                 if(user[mp[i].to]>tip)tip=user[mp[i].to];
     74                 que[tl++]=mp[i].to;tl%=mod;
     75                 if(mp[i].to==t)return 1;
     76             }
     77         }
     78     }
     79     return 0;
     80 }
     81 int dinic(int x,int y)
     82 {
     83     if(x==t)return y;
     84     int l=y,travel;
     85     for(int i=head[x];i;i=mp[i].next)
     86     {
     87         if(user[mp[i].to]==user[x]+1&&mp[i].dis>0)
     88         {
     89             travel=dinic(mp[i].to,min(mp[i].dis,y));
     90             y-=travel;
     91             mp[i].dis-=travel;
     92             mp[((i-1)^1)+1].dis+=travel;
     93             if(!y)break;
     94         }
     95     }
     96     if(y==l)user[x]=0;
     97     return l-y;
     98 }
     99 void work()
    100 {
    101     while(bfs())
    102     {
    103         tim=tip+1;
    104         ans+=dinic(s,Max);
    105     }
    106 }
    107 int main()
    108 {
    109     n=read();m=read();
    110     s=1;t=l(n,m);
    111     init();
    112     work();
    113     printf("%d
    ",ans);
    114     return 0;
    115 }
    Dinic
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<queue>
      6 #define Max 2147483640
      7 #define dis first
      8 #define pos second
      9 #define mk(A,B) make_pair(A,B)
     10 #define d(A,B,C) ((A-1)*m*2+m*(C-1)+B)
     11 using namespace std;
     12 typedef pair<int,int> nod;
     13 int read()
     14 {
     15     char ch=getchar();int cn=0,kin=1;
     16     while(ch>'9'||ch<'0'){if(ch=='-')kin=-1;ch=getchar();}
     17     while(ch>='0'&&ch<='9'){cn=cn*10+ch-48;ch=getchar();}
     18     return cn*kin;
     19 }
     20 struct ni
     21 {
     22     vector<int>s[2];
     23     int ml;
     24 }a[2000005];
     25 int n,m,t;
     26 priority_queue<nod,vector<nod>,greater<nod> >que;
     27 void get(int,int);
     28 void init();
     29 int main()
     30 {
     31     freopen("a.in","r",stdin);
     32     n=read()-1;m=read()-1;
     33     if(n==0||m==0)
     34     {
     35 
     36         if(n<m)swap(n,m);
     37         int la,ans=Max;
     38         for(int i=1;i<=n;++i)
     39         {
     40             la=read();
     41             ans=min(ans,la);
     42         }
     43         cout<<ans<<endl;return 0;
     44     }
     45     t=n*2*m+1;
     46     init();que.push(mk(0,0));
     47     int nw,d;
     48     while(!que.empty())
     49     {
     50         nw=que.top().second;d=que.top().first;que.pop();
     51         for(int i=0;i<a[nw].s[0].size();++i)
     52         {
     53             if(d+a[nw].s[1][i]<a[a[nw].s[0][i]].ml)
     54             {
     55                 a[a[nw].s[0][i]].ml=d+a[nw].s[1][i];
     56                 que.push(mk(a[a[nw].s[0][i]].ml,a[nw].s[0][i]));
     57             }
     58         }
     59     }
     60     cout<<a[t].ml<<endl;
     61     fclose(stdin);
     62     return 0;
     63 }
     64 void get(int x,int y)
     65 {
     66     int t1;
     67     t1=read();
     68     a[x].s[0].push_back(y);
     69     a[x].s[1].push_back(t1);
     70     a[y].s[0].push_back(x);
     71     a[y].s[1].push_back(t1);
     72 }
     73 void init()
     74 {
     75     for(int i=1;i<=n*2*m;++i)
     76     {
     77         a[i].ml=Max;
     78     }a[t].ml=Max;
     79     for(int i=1;i<=n+1;++i)
     80     for(int j=1;j<=m;++j)
     81     {
     82         if(i==1)
     83         get(d(i,j,1),t);
     84         else if(i==n+1)
     85         get(0,d(i-1,j,2));
     86         else
     87         get(d(i,j,1),d(i-1,j,2));
     88     }
     89     for(int i=1;i<=n;++i)
     90     for(int j=1;j<=m+1;++j)
     91     {
     92         if(j==1)
     93         get(d(i,j,2),0);
     94         else if(j==m+1)
     95         get(d(i,j-1,1),t);
     96         else
     97         get(d(i,j,2),d(i,j-1,1));
     98     }
     99     for(int i=1;i<=n;++i)
    100     for(int j=1;j<=m;++j)
    101     {
    102         get(d(i,j,1),d(i,j,2));
    103     }
    104 }
    最短路
  • 相关阅读:
    使用JS动态创建含有1000行的表格
    HashTable、HashMap、LinkedHashMap、TreeMap的比较
    移动节点
    WebLoigc的配置(生产模式与开发模式)
    海量数据查询问题--简单的理解
    Servlet中乱码问题
    九度 1369 字符串的排列
    九度 1349 数字在排序数组中出现的次数
    九度 1384 二维数组中的查找
    九度 1402 特殊的数
  • 原文地址:https://www.cnblogs.com/Zn-H/p/6414070.html
Copyright © 2011-2022 走看看