HDU - 3035 War(对偶图求最小割+最短路)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3035

题意

给个图,求把s和t分开的最小割。

分析

实际顶点和边非常多,不能用最大流来求解。这道题要用平面图求最小割的方法:

把面变成顶点,对每两个面相邻的边作一条新边。然后求最短路就是最小割了。

另外,外平面分成两个点,分别是源点和汇点,源点连左下的边,汇点连右上的边,这样跑出来才是正确的。

建图参考自:https://blog.csdn.net/accelerator_/article/details/40957675

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

const int MAXNODE = 1000005;
const int MAXEDGE = 3 * MAXNODE;

typedef int Type;
const Type INF = 0x3f3f3f3f;

struct Edge {
    int u, v;
    Type dist;
    Edge() {}
    Edge(int u, int v, Type dist) {
        this->u = u;
        this->v = v;
        this->dist = dist;
    }
};

struct HeapNode {
    Type d;
    int u;
    HeapNode() {}
    HeapNode(Type d, int u) {
        this->d = d;
        this->u = u;
    }
    bool operator < (const HeapNode& c) const {
        return d > c.d;
    }
};

struct Dijkstra {
    int n, m;
    Edge edges[MAXEDGE];
    int first[MAXNODE];
    int next[MAXEDGE];
    bool done[MAXNODE];
    Type d[MAXNODE];

    void init(int n) {
        this->n = n;
        memset(first, -1, sizeof(first));
        m = 0;
    }

    void add_Edge(int u, int v, Type dist) {
        edges[m] = Edge(u, v, dist);
        next[m] = first[u];
        first[u] = m++;
    }

    Type dijkstra(int s, int t) {
        priority_queue<HeapNode> Q;
        for (int i = 0; i < n; i++) d[i] = INF;
        d[s] = 0;
        memset(done, false, sizeof(done));
        Q.push(HeapNode(0, s));
        while (!Q.empty()) {
            HeapNode x = Q.top(); Q.pop();
            int u = x.u;
            if (done[u]) continue;
            done[u] = true;
            for (int i = first[u]; i != -1; i = next[i]) {
                Edge& e = edges[i];
                if (d[e.v] > d[u] + e.dist) {
                    d[e.v] = d[u] + e.dist;
                    Q.push(HeapNode(d[e.v], e.v));
                }
            }
        }
        return d[t];
    }
} gao;

typedef long long ll;

int n, m;

int main() {
    while (~scanf("%d%d", &n, &m)) {
        int u, v, w;
        gao.init(n * m * 4 + 2);
        int s = n * m * 4, t = n * m * 4 + 1;
        for (int i = 0; i < (n + 1); i++) {
            for (int j = 0; j < m; j++) {
                scanf("%d", &w);
                u = (i - 1) * m + j + n * m;
                v = i * m + j;
                if (i == 0) u = t;
                if (i == n) v = s;
                gao.add_Edge(u, v, w);
                gao.add_Edge(v, u, w);
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < (m + 1); j++) {
                scanf("%d", &w);
                u = n * m * 3 + i * m + j - 1;
                v = n * m * 2 + i * m + j;
                if (j == 0) u = s;
                if (j == m) v = t;
                gao.add_Edge(u, v, w);
                gao.add_Edge(v, u, w);
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf("%d", &w);
                u = i * m + j;
                v = n * m * 2 + i * m + j;
                gao.add_Edge(u, v, w);
                gao.add_Edge(v, u, w);
                scanf("%d", &w);
                v += n * m;
                gao.add_Edge(u, v, w);
                gao.add_Edge(v, u, w);
            }
            for (int j = 0; j < m; j++) {
                scanf("%d", &w);
                u = n * m + i * m + j;
                v = n * m * 2 + i * m + j;
                gao.add_Edge(u, v, w);
                gao.add_Edge(v, u, w);
                scanf("%d", &w);
                v += n * m;
                gao.add_Edge(u, v, w);
                gao.add_Edge(v, u, w);
            }
        }
        printf("%d\n", gao.dijkstra(s, t));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/fht-litost/p/9773497.html

时间: 2024-10-12 22:03:21

HDU - 3035 War(对偶图求最小割+最短路)的相关文章

HDU 3035 War(对偶图求最小割)

HDU 3035 War 题目链接 题意:根据图那样,给定一个网络,要求阻断s到t,需要炸边的最小代价 思路:显然的最小割,但是也显然的直接建图强行网络流会超时,这题要利用平面图求最小割的方法,把每一块当成一个点,共有边连边,然后每一个路径就是一个割,然后最短路就是最小割了 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace s

HDU 2435 There is a war (网络流-最小割)

There is a war Problem Description There is a sea. There are N islands in the sea. There are some directional bridges connecting these islands. There is a country called Country One located in Island 1. There is another country called Country Another

BZOJ_1001_狼抓兔子(平面图求最小割+对偶图求最短路)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1001 分析 平面图求最小割,转化成对偶图求最短路,经典. 注意: 1.优先队列是个大根堆. 2.Dijkstra可以带一个vis数组,也可以不带,因为一个点出来以后,它更新的的点和原本就在队列里的点都比它大,所以它不可能被更新得更小,之后这个点再出队时情况不比第一次更优,所以出队也不会有操作. 3.双向边,数组要开够(貌似不是第一次犯这个错误). 4.网上有人说m==1||n==1的情况可以

HDU 1565 (最大流+黑白染色化二分图求最小割)

http://acm.hdu.edu.cn/showproblem.php?pid=1565 思路:将横纵坐标和为偶尔染白色,其他染黑色,黑点连接源点,流量为该点的值,白点连接汇点,流量为该点的值,黑白点有相邻的就连边,值为无穷大.最后求最大流,即该图的最小割. PS:刚开始不明白为为什么最大流会等于最小割,为什么所有的点之和减去最小割就会等于答案. 我的理解是:整张图其实就跟连接管道一样,连接了黑点表示取了黑点那个值的流量,白点也是,而连接了相邻的黑白点求出的最大流就会是流量较小的那个的值.好

hdu 3987 求最小割条数最小

题意:    一个人要从起点  0  到达 n-1   n个点  m条路  ,我们求最少破坏路的条数使无法 从起点到达终点.题意很明显  ,求最小割条数最少,由于最小割流量虽然固定,但是其条数却不固定,可以破坏3条路,也可以破坏4条路,他们总流量相同才会出现这种情况. 题解:由于上述的情况,他们总流量相同但是条数不同,现在我们需要改变边的容量使得条数少边才是最小割,条数多的将不会是最小割. 官方题解有两种 ,我选择的是在残余网络中进行扩充流的操作,使的两个最小割不同,残余网络中,我进行所有边流量

HDU 6214 Smallest Minimum Cut 最小割,权值编码

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6214 题意:求边数最小的割. 解法: 建边的时候每条边权 w = w * (E + 1) + 1; 这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1) 道理很简单,如果原先两类割边都是最小割,那么求出的最大流相等 但边权变换后只有边数小的才是最小割了 乘(E+1)是为了保证边数叠加后依然是余数,不至于影响求最小割的结果 因为假设最小割=k,那么现在新

HDU 4289:Control(最小割)

http://acm.hdu.edu.cn/showproblem.php?pid=4289 题意:有n个城市,m条无向边,小偷要从s点开始逃到d点,在每个城市安放监控的花费是sa[i],问最小花费可以监控到所有小偷. 思路:求最小割可以转化为最大流.每个城市之间拆点,流量是sa[i],再增加一个超级源点S和s相连,增加一个超级汇点T,让d的第二个点和T相连.然后就可以做了. 1 #include <cstdio> 2 #include <algorithm> 3 #include

HDU 4289 Control (网络流-最小割)

Control Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to another one (the destination). You know their

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g