zoukankan      html  css  js  c++  java
  • BZOJ-1001 [BeiJing2006]狼抓兔子

    解题思路:

    这道题目是关于最小割的一道题目。

    最小割的经典算法是根据最大流最小割定理,将最小割化成最大流然后用dinic算法求解

    不过这题比较特殊,即使转换成最大流求最小割依旧不可能通过。因为时间和空间的双重限制,所以这道题的解法需要利用这个图的特殊性质。

    给出的图是一个平面图无疑,那么利用平面图的特殊性质解决这个问题会简单很多。

    将平面图转换成其对偶图,然后计算新的源点到新的汇点的最短路径即可得出结果。

    然后关于这个题目,有一篇资料写的很好推荐一发:传送门

    听说这题用dijkstra+heap速度更快。

    代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef struct node {
    	int v, cap, nxt;
    	node(int a = 0, int b = 0, int c = 0) {
    		v = a; cap = b; nxt = c;
    	}
    }Edge;
    
    const int maxn = 2100005;
    const int maxm = 6100005;
    const int inf = 0x3f3f3f3f;
    
    Edge edge[maxm];
    int tot, head[maxn];
    int vis[maxn], dis[maxn];
    
    void add(int u, int v, int cap) {
    	edge[tot] = Edge(v, cap, head[u]);
    	head[u] = tot++;
    	edge[tot] = Edge(u, cap, head[v]);
    	head[v] = tot++;
    }
    int spfa(int s, int t) {
    	int x;
    	Edge e;
    	queue<int> q;
    	while (!q.empty()) q.pop();
    	memset(vis, 0, sizeof(vis));
    	memset(dis, 0x3f, sizeof(dis));
    	
    	dis[s] = 0; vis[s] = 1; q.push(s);
    	while (!q.empty()) {
    		x = q.front(); q.pop(); vis[x] = 0;
    		for (int i = head[x]; ~i; i = edge[i].nxt) {
    			e = edge[i];
    			if (dis[x] + e.cap < dis[e.v]) {
    				dis[e.v] = dis[x] + e.cap;
    				if (!vis[e.v]) {
    					vis[e.v] = 1;
    					q.push(e.v);
    				}
    			}
    		}
    	}
    	return dis[t];
    }
    int main() {
    	int n, m, u, v, cap;
    	while (~scanf("%d%d", &n, &m)) {
    		if (n == 1 || m == 1) {
    			if (n > m) swap(n, m);
    			int ans = inf;
    			for (int i = 1, a; i < m; ++i) {
    				scanf("%d", &a);
    				ans = min(ans, a);
    			}
    			printf("%d
    ", ans == inf ? 0 : ans);
    			continue;
    		}
    		int s = 0, t = (m - 1) * 2 * (n - 1) + 1;
    		tot = 0;
    		memset(head, -1, sizeof(head));
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= m - 1; ++j) {
    				scanf("%d", &cap);
    				if (i == 1) { u = s; v = 2 * j; }
    				else if (i == n) { u = (m - 1) * (n - 2) * 2 + 2 * j - 1; v = t; }
    				else { v = (m - 1) * 2 * (i - 2) + 2 * j - 1; u = (m - 1) * 2 * (i - 1) + 2 * j; }
    				add(u, v, cap);
    				//printf("u = %d, v = %d, cap = %d
    ", u, v, cap);
    			}
    		}
    		for (int i = 1; i < n; ++i) {
    			for (int j = 1; j <= m; ++j) {
    				scanf("%d", &cap);
    				if (j == 1) { v = t; u = (m - 1)*(i - 1) * 2 + 1; }
    				else if (j == m) { u = s; v = (m - 1) * i * 2; }
    				else { u = (m - 1) * (i - 1) * 2 + 2 * (j - 1); v = u + 1; }
    				add(u, v, cap);
    				//printf("u = %d, v = %d, cap = %d
    ", u, v, cap);
    			}
    		}
    		for (int i = 1; i < n; ++i) {
    			for (int j = 1; j < m; ++j) {
    				scanf("%d", &cap);
    				u = (m - 1) * 2 * (i - 1) + 2 * j - 1; 
    				v = u + 1;
    				add(u, v, cap);
    				//printf("u = %d, v = %d, cap = %d
    ", u, v, cap);
    			}
    		}
    		printf("%d
    ", spfa(s, t));
    	}
    	return 0;
    }


  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179363.html
Copyright © 2011-2022 走看看