平面图网络流

首先推荐一个论文:周冬2008年集训队论文《浅析最大最小定理在信息学竞赛中的应用》

论文说的很详细,然后再写写我的总结吧。

首先先说说什么是平面图,或者说平面图的性质:

  1. (欧拉公式)如果一个连通的平面图有n个点,m条边和f个面,那么f = m - n + 2。
  2. 每个平面图G都有一个与其对偶的平面图G*。
    • G*中的每个点对应G中的一个面
    • 对于G中的每条边e,e属于俩个面f1,f2,加入边(f1*, f2*),e只属于一个面,加入回边(f*, f*)

然后说说平面图G与其对偶图G*的关系:

  1.  G的面数等于G*的点数,G*的点数等于G到面数,G与G*边数相等。
  2.  G*中的环与G中的割一一对应。如下图:

          

s-t平面图最大流的快速求法:

连接s-t得到一个附加面

求该图的对偶图G*,令附加面对应的点为s*,无界面对应的点为t*。

删去s*和t*间的边。这时一条s*到t*的一条路径就对应了s-t的一条割。更进一步,如果我们令每条边的长度等于它的容量,那么最小割的容量就等于最短路径的长度。

相关题目:

  •  HDU3870 Catch the Theves:题意描述:一群贼,要从城市A(1,1)到城市B(n,n)作案,警察需要在贼到达B之前将其逮捕,所以要安排警力去守住某些路,然后需要给警察付费,每段路的需要付的费可以不同,然后给出一个矩阵表示g[i][j]表示从城市(i,j)到(i+1,j)和(i,j+1)需要付给警察的费用,题目求最少的钱能够使所有的贼被抓?裸的平面图最大流。。。做法见上面描述。我傻逼最短路加边的时候加成单项的了。。wa了好多次。代码君:
  • View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 #include <vector>
     6 #include <iostream>
     7 using namespace std;
     8 
     9 const int maxn = 405 * 405;
    10 const int maxm = 4 * maxn;
    11 const int inf = 0x3f3f3f3f;
    12 int test, n, mp[444][444];
    13 
    14 struct Dijkstra {
    15     typedef pair<long long, int> T;
    16     vector<T> E[maxn];
    17     priority_queue<T, vector<T>, greater<T> > q;
    18     int d[maxn], cnt;
    19 
    20     void clearEdge() {
    21         for (int i = 0; i < maxn; i++)
    22             E[i].clear();
    23     }
    24 
    25     void addEdge(int u, int v, int w) {
    26         E[u].push_back(T(w, v));
    27         E[v].push_back(T(w, u));
    28     }
    29 
    30     void dijkstra(int s) {
    31         for (int i = 0; i < maxn; i++)
    32             d[i] = inf;
    33         cnt = 0;
    34         while (!q.empty()) q.pop();
    35         int u, v, du, dv;
    36         d[s] = 0; q.push(T(0, s));
    37         while (!q.empty()) {
    38             u = q.top().second;
    39             du = q.top().first;
    40             q.pop();
    41             if (d[u] != du) continue;
    42             for (vector<T>::iterator it = E[u].begin(); it != E[u].end(); it++) {
    43                 v = it->second; dv = du + it->first;
    44                 if (d[v] > dv) {
    45                     d[v] = dv; q.push(T(dv, v));
    46                 }
    47             }
    48         }
    49     }
    50 };
    51 Dijkstra g;
    52         
    53 int main() {
    54     scanf("%d", &test);
    55     for (int cas = 1; cas <= test; cas++) {
    56         scanf("%d", &n); g.clearEdge();
    57         for (int i = 1; i <= n; i++)
    58             for (int j = 1; j <= n; j++)
    59                 scanf("%d", &mp[i][j]);
    60         int s = 0, t = (n-1) * (n-1) + 1;
    61         for (int i = 1; i < n; i++) {
    62             //printf("%d %d %lld\n", s, i, mp[1][i]);
    63             g.addEdge(s, i, mp[1][i]);
    64             //printf("%d %d %lld\n", s, (n-1)*i, mp[i][n]);
    65             g.addEdge(s, (n-1)*i, mp[i][n]);
    66             //printf("%d %d %lld\n", 1+(n-1)*(i-1), t, mp[i][1]);
    67             g.addEdge(1+(n-1)*(i-1), t, mp[i][1]);
    68             //printf("%d %d %lld\n", (n-1)*(n-2)+i, t, mp[n][i]);
    69             g.addEdge((n-1)*(n-2)+i, t, mp[n][i]);
    70         }
    71         for (int i = 1; i < n; i++) {
    72             for (int j = 1; j < n; j++) {
    73                 if (i != n - 1) {
    74                     //printf("%d %d %lld\n", (i-1)*(n-1)+j, i*(n-1)+j, mp[i+1][j]);
    75                     g.addEdge((i-1)*(n-1)+j, i*(n-1)+j, mp[i+1][j]);
    76                 }
    77                 if (j != n - 1) {
    78                     //printf("%d %d %lld\n", (i-1)*(n-1)+j, (i-1)*(n-1)+j+1, mp[i][j+1]);
    79                     g.addEdge((i-1)*(n-1)+j, (i-1)*(n-1)+j+1, mp[i][j+1]);
    80                 }
    81             }
    82         }
    83         g.dijkstra(s);
    84         printf("%d\n", g.d[t]);
    85     }
    86     return 0;
    87 }

     

  • HDU4280 坑。。。

  • POJ2922 坑。。。

  • BZOJ1001 [Beijing2006]狼抓兔子:中文题,就不描述题意了。。裸的平面图网络流。。。做法如上。。。不过请允许我吐槽一下出题人的节操。。尼玛 n 和 m 竟然可以为1。。所以这种情况要特判一下。嗯~又wa了好多次。。。代码君:

    View Code
  • BZOJ2007 

 

posted @ 2013-04-19 20:00  SDU_Phonism  阅读(458)  评论(0编辑  收藏  举报