• 【平面图最小割】BZOJ1001- [BeiJing2006]狼抓兔子


    【题目大意】
    左上角点为(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只狼伏击,求封锁道路的最小狼数。

    【思路】
    显然这是最小割,但是最小割效率太低。可以发现这是一张平面图,根据平面图的性质,平面图最小割=对偶图的最短路。所谓对偶图,简单理解就是把面转为点,然后将面之间的边作为连接两个点的边。本题中建立的对偶图如下:

    显然可以发现,最短路必然是最小割。

    【错误点】
    注意一下面转点后,对偶图点的数量和原来点的数量不一样,大概为2倍,数组要开足够大,否则RE!

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 #include<queue>
     7 #include <utility>
     8 #define S 0
     9 #define T 2*(m-1)*(n-1)+1
    10 using namespace std;
    11 const int MAXN=2000000;
    12 const int INF=0x7fffffff;
    13 struct edge
    14 {
    15     int fr,to,len;
    16 };
    17 int n,m,w;
    18 vector<edge> E[MAXN];
    19   
    20 void addedge(int u,int v,int w)
    21 {
    22     //cout<<"!"<<u<<' '<<v<<' '<<w<<endl;
    23     E[u].push_back((edge){u,v,w});
    24     E[v].push_back((edge){v,u,w});
    25 }
    26   
    27 int dijkstra()
    28 {
    29     priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > que;
    30     int dis[MAXN],vis[MAXN];
    31     memset(vis,0,sizeof(vis));
    32     for (int i=S+1;i<=T;i++) dis[i]=INF;
    33     dis[S]=0;
    34     que.push(make_pair<int,int>(0,S));
    35     while (!que.empty())
    36     {
    37         int head=que.top().second;que.pop();
    38         if (!vis[head])
    39         {
    40             vis[head]=1;
    41             for (int i=0;i<E[head].size();i++)
    42             {
    43                 edge Edge=E[head][i];
    44                 if (!vis[Edge.to] && dis[Edge.to]>dis[Edge.fr]+Edge.len)
    45                 {
    46                     dis[Edge.to]=dis[Edge.fr]+Edge.len;
    47                     que.push(make_pair<int,int>(dis[Edge.to],Edge.to));
    48                 }
    49             }
    50         }
    51     }
    52     return (dis[T]);
    53 }
    54   
    55 void init()
    56 {
    57     for (int i=0;i<n;i++)    
    58         for (int j=0;j<m-1;j++)
    59         {
    60             scanf("%d",&w);
    61             if (i==0) addedge(2*(j+1),T,w);
    62                 else if (i==n-1) addedge(S,(n-2)*(m-1)*2+2*j+1,w);
    63                     else addedge((i-1)*(m-1)*2+2*j+1,i*(m-1)*2+2*j+2,w);
    64         }
    65     for (int i=0;i<n-1;i++)
    66         for (int j=0;j<m;j++)
    67         {
    68             scanf("%d",&w);
    69             if (j==0) addedge(S,i*2*(m-1)+1,w);
    70                 else if (j==m-1) addedge((i+1)*2*(m-1),T,w);
    71                     else addedge(i*2*(m-1)+j*2,i*2*(m-1)+2*j+1,w);
    72         }
    73     for (int i=0;i<(n-1);i++)
    74         for (int j=0;j<(m-1);j++) 
    75         {
    76             scanf("%d",&w);
    77             //cout<<i<<' '<<j<<' ';
    78             addedge(i*2*(m-1)+2*j+1,i*2*(m-1)+2*j+2,w);
    79         }
    80 }
    81   
    82 int main()
    83 {
    84     scanf("%d%d",&n,&m);
    85     if (n==1 && m==1) cout<<0<<endl;
    86         else
    87         {
    88             init();
    89             cout<<dijkstra()<<endl;
    90         }
    91     return 0;
    92 }
  • 相关阅读:
    (6)在树莓派上截屏的方法
    (7)树莓派读物USB摄像头
    (4)给树莓派安装中文输入法Fcitx及Google拼音输入法
    (3)使用Android手机作为树莓派的屏幕
    (2)在树莓派安装运行在Python3上的OpenCV
    相机靶面尺寸和视场角换算
    STM32F103C8T6在Arduino IDE里编程
    项目(二) esp32-cam 网页图像人脸
    开发(一) ardunio环境配置 针对esp32-cam 更多例程
    [转] Compile、Make和Build的区别
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5679699.html
Copyright © 2020-2023  润新知