• [BZOJ 2007] [Noi2010] 海拔 【平面图最小割(对偶图最短路)】


    题目链接:BZOJ - 2007

    题目分析

    首先,左上角的高度是 0 ,右下角的高度是 1。那么所有点的高度一定要在 0 与 1 之间。然而选取 [0, 1] 的任何一个实数,都可以用整数 0 或 1 来替换,获得同样的效果。

    虽然输出的答案要求是四舍五入到整数,但其实答案就是一个整数!

    那么高度就一定是 0 或 1 了,并且还有一点,所有选 0 的点都连通,所有选 1 的点都联通。因为如果一个选 0 的点被选 1 的点包围,那么它选 1 更优。

    于是整个图中所有的点分成了与左上角相连的集合 A ,与右下角相连的集合 B 。从集合 A 向 B 的边权会计入答案。这就是最小割模型。

    这是一个规则的平面图,平面图最小割等于对偶图最短路

    建立对偶图:

    1)增加一条从 S 到 T 的边,成为 ST 边。这条边把原图中外围无限大的平面部分分割成了一个有限部分 S’ 和无限部分 T’。S’ 与 T’ 就是对偶图的起点和终点。

    2)将平面的每个部分看做一个虚拟点,每条边对应一条连接虚拟点的边。但是 ST 边不对应对偶图中的边。

    对偶图的一条最短路就对应了原图的一个最小割。

    原图的每一条单向边对应对偶图的边的方向可以画个图帮助确定。可以看看从 S’ 到 T’ 的路径中哪些方向的边计入最小割答案,也应是最短路答案。

    写 dijkstra !卡 SPFA!

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int MaxN = 500 + 5, INF = 999999999;
    
    int n, S, T;
    int Map[MaxN][MaxN][5], d[MaxN * MaxN];
    
    bool Visit[MaxN * MaxN];
    
    inline int Calc(int x, int y) {return (x - 1) * n + y;}
    
    struct Edge 
    {
    	int v, w;
    	Edge *Next;
    } E[MaxN * MaxN * 4], *P = E, *Point[MaxN * MaxN];
    
    inline void AddEdge(int x, int y, int z) {
    	++P; P -> v = y; P -> w = z;
    	P -> Next = Point[x]; Point[x] = P;
    }
    
    struct ES
    {
    	int x, y;
    	ES() {}
    	ES(int a, int b) {
    		x = a; y = b;
    	}
    };
    
    struct Cmp
    {
    	bool operator () (ES e1, ES e2) {
    		return e1.y > e2.y;
    	}
    };
    
    priority_queue<ES, vector<ES>, Cmp> Q;
    
    int main() 
    {
    	scanf("%d", &n);
    	//Input data...
    	for (int i = 1; i <= n + 1; ++i) 
    		for (int j = 1; j <= n; ++j) 
    			scanf("%d", &Map[i][j][0]);
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= n + 1; ++j)
    			scanf("%d", &Map[i][j][1]);
    	for (int i = 1; i <= n + 1; ++i) 
    		for (int j = 2; j <= n + 1; ++j) 
    			scanf("%d", &Map[i][j][2]);
    	for (int i = 2; i <= n + 1; ++i)
    		for (int j = 1; j <= n + 1; ++j)
    			scanf("%d", &Map[i][j][3]);
    	//Input done...
    	S = n * n + 1; T = n * n + 2;
    	for (int i = 1; i <= n + 1; ++i) {
    		for (int j = 1; j <= n + 1; ++j) {
    			if (j <= n) {	
    				if (i == 1) AddEdge(Calc(i, j), T, Map[i][j][0]);
    				else if (i == n + 1) AddEdge(S, Calc(i - 1, j), Map[i][j][0]);
    				else AddEdge(Calc(i, j), Calc(i - 1, j), Map[i][j][0]); 
    			}
    			if (j > 1) {
    				if (i == 1) AddEdge(T, Calc(i, j - 1), Map[i][j][2]);
    				else if (i == n + 1) AddEdge(Calc(i - 1, j - 1), S, Map[i][j][2]);
    				else AddEdge(Calc(i - 1, j - 1), Calc(i, j - 1), Map[i][j][2]);
    			}
    			if (i <= n) {
    				if (j == 1) AddEdge(S, Calc(i, j), Map[i][j][1]);
    				else if (j == n + 1) AddEdge(Calc(i, j - 1), T, Map[i][j][1]);
    				else AddEdge(Calc(i, j - 1), Calc(i, j), Map[i][j][1]);
    			}
    			if (i > 1) {
    				if (j == 1) AddEdge(Calc(i - 1, j), S, Map[i][j][3]);
    				else if (j == n + 1) AddEdge(T, Calc(i - 1, j - 1), Map[i][j][3]);
    				else AddEdge(Calc(i - 1, j), Calc(i - 1, j - 1), Map[i][j][3]);
    			}
    		}
    	}
    	//Build_Edge done...
    	memset(Visit, 0, sizeof(Visit));
    	for (int i = 1; i <= T; ++i) d[i] = INF;
    	d[S] = 0;
    	while (!Q.empty()) Q.pop();
    	ES Now;
    	for (int i = 1; i <= T; ++i) Q.push(ES(i, d[i]));
    	while (!Q.empty()) {
    		Now = Q.top(); Q.pop(); 
    		if (Visit[Now.x]) continue;
    		if (Now.x == T) break;
    		Visit[Now.x] = true;
    		for (Edge *j = Point[Now.x]; j; j = j -> Next) {
    			if (d[Now.x] + j -> w < d[j -> v]) {
    				d[j -> v] = d[Now.x] + j -> w;
    				Q.push(ES(j -> v, d[j -> v]));
    			}
    		}
    	}
    	printf("%d
    ", d[T]);
    	return 0;
    }
    

      

  • 相关阅读:
    AxureRP的学习
    http状态码的含义
    10.mongoDB给所有文档添加字段
    ip正则匹配
    express使用socketIO,前后端跨域
    express后端配置,实现跨域
    https带来的express后台部署到服务器所引发的问题
    前台:VueSocketIOExt+socket.io-client,后台socket.io的聊天环境搭载
    即时通讯框架SocketIO
    9.mongoDB新增文档,若文档已存在,则不新增,若文档不存在,则新增
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4252930.html
Copyright © 2020-2023  润新知