• 【BZOJ 1001】狼抓兔子 对偶图+SPFA


      这道题是求图的最小割,也就是用最大流。但因为边太多,最大流算法会T,因此不能用最大流算法。

      因为这是个平面图,所以求平面图的最小割可以使用特殊的技巧就是求对偶图然后求对偶图的最短路。把每个面看成一个点f*,f*之间边的权值就是之前原来的点f之间与f*的边交叉的边的权值。(说的不清楚,大家可以看其他博客,讲得都很好)

      这样建了一个对偶图G*,由此可见,对偶图G*的一条路对应着原图G的一个割。所以求G*的最短路就相当于求G的最小割。

      以后遇到平面图求最小割就把它转化成对偶图再求最短路,这样时间效率会大大提高。

    88732 kb 3572 ms C++/Edit 2195 B
      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 int point[2000103],next[6000103],v[6000103],c[6000103];
      7 int cnt=0,s,t,n,m,dist[2000103];
      8 bool vis[2000103];
      9 queue<int>q;
     10 void insect(int x,int y,int z)
     11 {cnt++;next[cnt]=point[x];point[x]=cnt;v[cnt]=y;c[cnt]=z;}
     12 void in1()
     13 {
     14     int i,j,num;
     15     for (j=1;j<m;++j)
     16     {
     17         scanf("%d",&num);
     18         insect(j*2,t,num);
     19         insect(t,j*2,num);
     20     }
     21     for (i=2;i<n;++i)
     22      for (j=1;j<m;++j)
     23      {
     24          scanf("%d",&num);
     25          insect((i-1)*(m-1)*2+j*2,(i-1)*(m-1)*2+j*2-m*2+1,num);
     26          insect((i-1)*(m-1)*2+j*2-m*2+1,(i-1)*(m-1)*2+j*2,num);
     27      }
     28     for (j=1;j<m;++j)
     29     {
     30         scanf("%d",&num);
     31         insect(s,(n-2)*2*(m-1)+j*2-1,num);
     32         insect((n-2)*2*(m-1)+j*2-1,s,num);
     33     }
     34 }
     35 void in2()
     36 {
     37     int i,j,num,xx;
     38     for (i=1;i<n;++i)
     39     {
     40         scanf("%d",&num); xx=(i-1)*(m-1)*2+1;
     41         insect(s,xx,num);
     42         insect(xx,s,num);
     43         for (j=2;j<m;++j)
     44         {
     45             scanf("%d",&num); xx+=2;
     46             insect(xx-1,xx,num);
     47             insect(xx,xx-1,num);
     48         }
     49         scanf("%d",&num);
     50         insect(xx+1,t,num);
     51         insect(t,xx+1,num);
     52     }
     53 }
     54 void in3()
     55 {
     56     int i,j,num;
     57     for (i=1;i<n;++i)
     58      for (j=1;j<m;++j)
     59      {
     60          scanf("%d",&num);
     61          insect((i-1)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,num);
     62          insect((i-1)*(m-1)*2+j*2,(i-1)*(m-1)*2+j*2-1,num);
     63      }
     64 }
     65 void init()
     66 {
     67     scanf("%d %d
    ",&n,&m);
     68     s=0; t=(n-1)*(m-1)*2+1;
     69     in1();
     70     in2();
     71     in3();
     72 }
     73 void spfa()
     74 {
     75     int num,mp;
     76     dist[s]=0;
     77     q.push(s);
     78     while (!q.empty())
     79     {
     80         num=q.front(); q.pop(); vis[num]=0;
     81         mp=point[num];
     82         while (mp>0)
     83         {
     84             if (dist[v[mp]]>dist[num]+c[mp])
     85             {
     86                 dist[v[mp]]=dist[num]+c[mp];
     87                 if (vis[v[mp]]==0)
     88                 {
     89                     vis[v[mp]]=1; q.push(v[mp]);
     90                 }
     91             }
     92             mp=next[mp];
     93         }
     94     }
     95     printf("%d
    ",dist[t]);
     96 }
     97 int main()
     98 {
     99     memset(dist,127,sizeof(dist));
    100     memset(point,0,sizeof(point));
    101     memset(next,0,sizeof(next));
    102     memset(vis,0,sizeof(vis));
    103     memset(v,0,sizeof(v));
    104     init();
    105     spfa();
    106     return 0;
    107 }
    View Code
      •平面图性质
      1.(欧拉公式)如果一个连通的平面图有n个点,m条边和f个面,那么f=m-n+2
      2.每个平面图G都有一个与其对偶的平面图G*n,G*中的每个点对应G中的一个面n
     
      
    NOI 2017 Bless All
  • 相关阅读:
    什么是Portal!
    Maven 让事情变得简单
    HTTP协议详解
    函数实现不放在头文件的原因,及何时可以放头文件的情况
    Linux中的内存管理(四)Heap
    寿星万年历Lua实现
    TCP epoll触发后只accept一次带来的问题
    生产者消费者问题
    Windows SDK 实现不规则窗口
    论迭代式的产品开发方法
  • 原文地址:https://www.cnblogs.com/abclzr/p/5033461.html
Copyright © 2020-2023  润新知