当前位置:编程学习 > C/C++ >>

poj 2822 & hdu 4280 <平面图网络流>

对于10^5个点10^6条边的网络流,一般做法无法高效解决,如果所有边都是双向边且网络能构成一个平面图,则可以通过求解对偶图的最短路求解,复杂度为O(M*log(M)),转化方法类似于《平面图S-T最小割》, 与S-T最小割平面图较规则不同,难点在于将一张图的块求出。大体分如下几步进行:
①把所有的边都拆成两条有向边,自环删掉。
②将每条有向边在另一个图G‘中用一个点表示。
③考察原图中的每个顶点,将所有的与之相连的边极角排序。
④遍历每条入边。将其后继设为与之顺时针相邻的出边。也就是在G’中连一条从这个入边的点到其后继的有向边。
###注意(S, T)的那条新加边要特殊处理。
⑤在G'中就是一些不相交的有向环。每个有向环就对应一个区域。找出了所有的区域,我们要的那张图就简单了。
⑥根据对偶图构图,求得s-t之间最短路即是对应的最小割
###至于“死胡同”问题(构不成平面的边)这样会形成一个特殊的区域,相当于进易做图胡同再出来。但是答案不会受到影响,所以直接忽略。
 hdu 4280 Island Transport代码:
[cpp] 
#pragma comment(linker, "/STACK:16777216") 
#include <cmath> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <algorithm> 
#include <vector> 
#include <set> 
using namespace std; 
const int maxn = 100010; 
const int maxm = 100010; 
const double inf = 1 << 28; 
struct node { 
    int be, ne; 
    double val; 
    void init(int b, int e, double v) { 
        be = b; 
        ne = e; 
        val = v; 
    } 
}; 
 
int cmp(double a, double b) { 
    double eps = 1e-8; 
    if (a - b > eps) 
        return 1; 
    else if (a - b >= -eps) 
        return 0; 
    else 
        return -1; 

struct SPFA { 
    node buf[maxm * 2]; 
    int len, E[maxn], queue[maxn]; 
    double d[maxn]; 
    void init() { 
        memset(E, -1, sizeof(E)); 
        len = 0; 
    } 
    void add(int a, int b, double v) { 
        if (a == b) 
            return; 
        buf[len].init(b, E[a], v); 
        E[a] = len++; 
    } 
    int vis[maxn]; 
    double solve(int s, int t) { 
        int head = 0, tail = 0; 
        memset(vis, 0, sizeof(vis)); 
        memset(d, 255, sizeof(d)); 
        d[s] = 0; 
        queue[(tail++) % maxn] = s; 
        vis[s] = true; 
        int a, b; 
        while (head != tail) { 
            a = queue[(head++) % maxn]; 
            vis[a] = 0; 
            for (int i = E[a]; i != -1; i = buf[i].ne) { 
                b = buf[i].be; 
                if (cmp(d[a] + buf[i].val, d[b]) == -1) { 
                    d[b] = d[a] + buf[i].val; 
                    if (!vis[b]) { 
                        vis[b] = 1; 
                        queue[(tail++) % maxn] = b; 
                    } 
                } 
            } 
        } 
        return d[t]; 
    } 
} sp; 
struct arch { 
    int in, out; 
    double angle; 
    arch(int a, int b, double c) { 
        in = a; 
        out = b; 
        angle = c; 
    } 
    bool operator <(const arch& oth) const { 
        return cmp(angle, oth.angle) == -1; 
    } 
}; 
int n, m; 
double px[maxn], py[maxn], cap[maxm]; 
vector<arch> vertex[maxn]; 
void init() { 
    scanf("%d%d", &n, &m); 
    double left = inf, right = -inf; 
    int s = 0, t = 0; 
    for (int i = 1; i <= n; i++) { 
        scanf("%lf%lf", &px[i], &py[i]); 
        vertex[i].clear(); 
        if (px[i] < left) { 
            s = i; 
            left = px[i]; 
        } 
        if (px[i] > right) { 
            right = px[i]; 
            t = i; 
        } 
    } 
    int a, b; 
    for (int i = 0; i < m; i++) { 
        scanf("%d%d%lf", &a, &b, cap + i); 
        if (a == b) { 
            m--; 
            i--; 
            continue; 
        } 补充:软件开发 , C++ ,

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,