- 浏览: 222917 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
higkoo:
Keepalived在Reload的时候都会提示:Jan 24 ...
open 创建文件并读写的错误--bad file descriptor -
panyanyany:
iminto 写道你忽悠人呢。。。 serial, 明明是po ...
通过 Zend_Db 向 mysql 写入 null 值的问题 -
iminto:
你忽悠人呢。。。 serial, 明明是postgre SQL ...
通过 Zend_Db 向 mysql 写入 null 值的问题 -
基德KID.1412:
y神写得如此的美啊,太特么好勒!特此顶上! ----KIDx
杭电 hdu 1394 Minimum Inversion Number 【线段树 + 详细注释 + 有难度】 -
基德KID.1412:
顶y哥!
【最短路+bfs+剪枝】杭电 hdu 2433 Travel
Dinic 算法
/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://poj.org/problem?id=1698 Name : 1698 Alice's Chance Date : Wednesday, February 01, 2012 Time Stage : many hours Result: 9763175 panyanyany 1698 Accepted 404K 16MS C++ 4085B 2012-02-01 19:22:35 Test Data : Review : 传说是最快的最大流算法,果然名不虚传啊!如果看不懂的,建议先看看这篇文章: 王欣上《浅谈基于分层思想的网络流算法》.doc 然后,一开始看的大牛的解题报告: http://www.cnblogs.com/littlex/archive/2011/08/17/2142766.html 没有注释很伤心啊,于是我的这个注了很多释,希望以后的同学能看明白~~ //----------------------------------------------------------------------------*/ #include <cstdio> #include <CSTRING> using namespace std ; #define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value #define max(x, y) ((x) > (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y)) #define INF (0x3f3f3f3f) #define MAXN 401 #define MAXE 16000 struct EDGE { int u, v, c, n ; }; int n, m, eCnt ; int map[MAXN][MAXN], dist[MAXN], vertex[MAXN], q[MAXN] ; EDGE edge[MAXE] ; void init () { eCnt = 0 ; MEM (vertex, -1) ; } void insert (int u, int v, int c) { edge[eCnt].u = u ; edge[eCnt].v = v ; edge[eCnt].c = c ; edge[eCnt].n = vertex[u] ; vertex[u] = eCnt++ ; edge[eCnt].u = v ; edge[eCnt].v = u ; edge[eCnt].c = 0 ; // 一开始这里是赋值的 c ,结果很悲剧~~ edge[eCnt].n = vertex[v] ; vertex[v] = eCnt++ ; } int dinic (int beg, int end) { int ans = 0 ; while (true) { int head, tail, u, v, e ; MEM(dist, -1) ; head = tail = 0 ; q[tail++] = beg ; dist[beg] = 0 ; // 广搜,构建层次图 while (head < tail) { v = q[head++] ; for (e = vertex[v] ; e != -1 ; e = edge[e].n) { u = edge[e].u ; int to = edge[e].v ; int cost = edge[e].c ; if (cost > 0 && dist[to] == -1) { dist[to] = dist[u] + 1 ; q[tail++] = to ; if (to == end) { head = tail ; break ; } } } } if (dist[end] == -1) break ; // v 表示增广路径的先头顶点 v = beg ; tail = 0 ; while (true) { // printf("--- tail:%d ", tail) ; if (v == end) { int i, flow = INF, ebreak ; // 寻找此路径可增加的最大流量 for (i = 0 ; i < tail ; ++i) if (flow > edge[q[i]].c) { flow = edge[q[i]].c ; ebreak = i ; } ans += flow ; // 根据刚才找到的最大流,更新此路径上的所有边 for (i = 0 ; i < tail ; ++i) { edge[q[i]].c -= flow ; // 正向边减流 edge[q[i]^1].c += flow ; // 反向边加流 } // 增广路径的先头顶点退至0流量的正向边的起始顶点 v = edge[q[ebreak]].u ; tail = ebreak ; // printf ("end --- v:%d ebreak:%d, ans:%d\n", v, ebreak, ans) ; } // 寻找有无可以继续增广的边 // 即,测试所有从顶点 v 起始的边中,是否有可以增广的边 // find a way from e to any vertex in "layers" for (e = vertex[v] ; e != -1 ; e = edge[e].n) { // 为了避免 -1 + 1 == 0 的情况,需要测试 dist[edge[e].u] > -1 // 其实这一步貌似可以省略,因为既然能够作为增广路径的先头顶点, // 其必然就在层次图中,因此 dist[u] 也就一定会 大于 -1 if (edge[e].c > 0 && //dist[edge[e].u] > -1 && dist[edge[e].u]+1 == dist[edge[e].v]) { // printf ("dist[%d]+1 == dist[%d]: %d+1 == %d\n", // edge[e].u, edge[e].v, dist[edge[e].u], dist[edge[e].v]) ; break ; } } // printf ("v:%d, e:%d, edge[%d]: u:%d, v:%d, c:%d, n:%d\n", // v, e, e, edge[e].u, edge[e].v, edge[e].c, edge[e].n) ; // system ("pause 1>>nul 2>>nul") ; // 不能从 vertex[v] 所指向的边找到增广路 if (e == -1) // no way from current edge's next vertex { // 路径队列中已经没有边了 if (tail == 0) // no edges in queue break ; // 既然 vertex[v] 所指向的边已经无路可通了 // 那么就应该把该边的目的顶点从层次图中删除 // 一开始写成了 dist[edge[q[--tail]].u] = -1 // 结果一直死循环……本程序所有的注释代码,都是为此错误服务的…… dist[edge[q[--tail]].v] = -1 ; // 增广路径退一条边,回到 vertex[v] 所在边的前一个顶点 v = edge[q[tail]].u ; // backward to previous vertex // printf ("e == -1 ----- v:%d, tail:%d\n", v, tail) ; } else // put the edge in queue { // 发现一条边可用,于是加入到增广路径队列中 q[tail++] = e ; // 将新边的目的顶点设为增广路径的先头顶点 v = edge[e].v ; } // puts ("") ; } } return ans ; } int main () { int i, j, k ; int tcase, D, W, days[8], maxW, des, sum ; while (scanf ("%d", &tcase) != EOF) { while (tcase--) { init () ; maxW = sum = 0 ; scanf ("%d", &n) ; for (i = 1 ; i <= n ; ++i) { for (j = 1 ; j <= 7 ; ++j) scanf ("%d", &days[j]) ; scanf ("%d%d", &D, &W) ; maxW = max(maxW, W) ; sum += D ; insert (0, i, D) ; // edges for each films // edges from film to days for (j = 0 ; j < W ; ++j) for (k = 1 ; k <= 7 ; ++k) { if (days[k]) { insert(i, j*7+k+n, 1) ; } } } // edges from every day to destination des = maxW*7+n+1 ; for (i = n + 1 ; i < des ; ++i) insert(i, des, 1) ; int ans = dinic (0, des) ; puts (ans == sum ? "Yes" : "No") ; } } return 0 ; }
Edmonds_Karp 解法
/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://poj.org/problem?id=1698 Name : 1698 Alice's Chance Date : Saturday, January 28, 2012 Time Stage : Many hours Result: 9749311 panyanyany 1698 Accepted 804K 860MS C++ 2637B 2012-01-28 13:52:50 Test Data : Review : 一开始 end 是400,cnt是401,直接TLE。 //----------------------------------------------------------------------------*/ #include <cstdio> #include <CSTRING> #include <queue> #include <algorithm> #include <vector> using namespace std ; #define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value #define max(x, y) ((x) > (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y)) #define INF (0x3f3f3f3f) #define MAXN 401 #define D 8 #define W 9 int n, m ; int flow[MAXN], map[MAXN][MAXN], pre[MAXN] ; int Mark_Point (int beg, int end, int cnt) { int i, t ; queue<int> q ; MEM (pre, -1) ; flow[beg] = INF ; pre[beg] = 0 ; q.push (beg) ; while (!q.empty ()) { t = q.front () ; q.pop () ; if (t == end) break ; for (i = 0 ; i < cnt ; ++i) { if (pre[i] == -1 && map[t][i]) { // printf ("%d-->%d ", t, i) ; pre[i] = t ; flow[i] = min (flow[t], map[t][i]) ; q.push (i) ; } } } if (pre[end] == -1) return -1 ; return flow[end] ; } int Edmonds_Karp (int beg, int end, int cnt) { int incr, step, curr, prev ; incr = 0 ; while ((step = Mark_Point (beg, end, cnt)) != -1) { incr += step ; curr = end ; while (curr != beg) { prev = pre[curr] ; map[prev][curr] -= step ; map[curr][prev] += step ; curr = prev ; } } return incr ; } int main () { int i, j, k ; int tcase, sum, maxday ; int w[10] ; while (scanf ("%d", &tcase) != EOF) { while (tcase--) { scanf ("%d", &n) ; MEM (map, 0) ; sum = maxday = 0 ; for (i = 1 ; i <= n ; ++i) { // MEM (w, 0) ; for (j = 1 ; j <= 9 ; ++j) scanf ("%d", &w[j]) ; sum += w[D] ; map[0][i] = w[D] ; maxday = max (maxday, w[W]) ; for (j = 0 ; j < w[W] ; ++j) { for (k = 1 ; k <= 7 ; ++k) { map[i][k+j*7+n] = w[k] ; // printf ("%d-->%d == %d , ", i, k+j*7+20, w[k]) ; // map[k+j*7+20][400] |= w[k] ; // maxd = max (maxd, k+j*7+20) ; } } } maxday *= 7 ; for (i = n + 1 ; i <= maxday + n ; ++i) map[i][maxday+1+n] = 1 ; // printf ("\n----%d \n", Edmonds_Karp (0, maxday+1+n, maxday+2+n)) ; if (Edmonds_Karp (0, maxday+1+n, maxday+2+n) == sum) puts ("Yes") ; else puts ("No") ; } } return 0 ; }
二分图解法
/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://poj.org/problem?id=1698 Name : 1698 Alice's Chance Date : Saturday, January 28, 2012 Time Stage : Many hours Result: 9748843 panyanyany 1698 Accepted 1892K 266MS C++ 1798B 2012-01-28 10:43:31 Test Data : Review : 网络流 dinic 算法还不会,先用二分图来做…… 参考了一下解题报告: http://blog.csdn.net/zxy_snow/article/details/6242668 //----------------------------------------------------------------------------*/ #include <cstdio> #include <CSTRING> #include <queue> #include <algorithm> #include <vector> using namespace std ; #define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value #define max(x, y) ((x) > (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y)) #define INF (0x3f3f3f3f) #define MAXN 401 bool cover[MAXN] ; int n, m, film_day ; int map[1100][MAXN], w[10], link[MAXN] ; int find (int cur) { int i ; for (i = 1 ; i <= m ; ++i) { if (cover[i] == false && map[cur][i]) { cover[i] = true ; if (!link[i] || find (link[i])) { link[i] = cur ; return true ; } } } return false ; } int main () { int i, j, k, l ; int tcase, sum ; scanf ("%d", &tcase) ; while (tcase--) { MEM (map, 0) ; m = 0 ; scanf ("%d", &n) ; film_day = 0 ; for (i = 1 ; i <= n ; ++i) { for (j = 1 ; j <= 9 ; ++j) { scanf ("%d", &w[j]) ; } for (l = film_day + 1 ; l <= film_day + w[8] ; ++l) { for (j = 0 ; j < w[9] ; ++j) { for (k = 1 ; k <= 7 ; ++k) { map[l][k+j*7] = w[k] ; m = max (m, k+j*7) ; } } } film_day += w[8] ; } sum = 0 ; MEM (link, 0) ; for (i = 1 ; i <= film_day ; ++i) { MEM (cover, 0) ; sum += find (i) ; } printf ("%s\n", sum == film_day ? "Yes" : "No") ; } return 0 ; }
发表评论
-
【最大流+dinic+二分枚举】北大 poj 3189 Steady Cow Assignment
2012-02-13 21:23 1021/* THE PROGRAM IS MADE BY PYY ... -
【最大流+dinic+二分】北大 poj 2455 Secret Milking Machine
2012-02-12 21:55 1189/* THE PROGRAM IS MADE BY PYY ... -
【最大流+floyd+二分+dinic】北大 poj 2112 Optimal Milking
2012-02-11 21:14 1140/* THE PROGRAM IS MADE BY PYY ... -
【最大流+dinic】北大 poj 1459 Power Network
2012-02-02 19:55 1065/* THE PROGRAM IS MADE BY ... -
【最大流+模板题】杭电 hdu 3549 Flow Problem
2012-01-04 00:45 1619/* THE PROGRAM IS MADE BY ... -
【最大流】北大 poj 1274 The Perfect Stall
2012-01-01 17:54 1543/* THE PROGRAM IS MADE BY ... -
【最大流】北大 poj 1273 Drainage Ditches
2012-01-01 16:15 1080/* THE PROGRAM IS MADE BY ...
相关推荐
本文将详细介绍Dinic算法,这是一种高效的求解网络最大流的算法。 首先,我们要理解什么是最大流。在网络流问题中,我们有一个带权重的有向图,其中每个边代表一个可以传输流量的连接,每条边都有一个容量限制。...
Edmonds-Karp算法和Dinic算法是解决这类问题的两种著名算法,它们都用于寻找一个图的最大流。下面将详细讨论这两个算法以及它们在C++中的实现。 首先,让我们了解Edmonds-Karp算法。这个算法基于增广路径的概念,即...
最大流的Dinic算法,时间复杂度O(EV^2),代码简单而高效
尽管不是最快速的算法(比如Ford-Fulkerson的改进版Edmonds-Karp算法),但Dinic算法在某些特定结构的网络上表现更优。 在实际应用中,理解并熟练掌握Dinic算法可以帮助解决许多与流量和资源分配相关的复杂问题。...
【二分图顶点覆盖->最小割->最大流->Dinic算法求解】 解题报告+AC代码 http://hi.csdn.net/!s/WKVPR0 ----> 我的所有POJ解题报告 http://blog.csdn.net/lyy289065406/article/details/6642573
[Din70]Algorithm for solution of a problem of maximum flow in a network with power estimation.pdf 最大流最高标号法(DINIC法)的论文原文
最大网络流问题在图论和运筹学中占有重要地位,它主要研究在一个有向图中,从源点到汇点能通过的最大流量。Dinic算法是由苏联计算机科学家E. A. Dinic于1970年提出的,是一种解决此类问题的有效算法。该算法基于层的...
最大流问题在图论和网络优化中占有重要地位,它旨在寻找从源点到汇点在网络中的最大流量,而不会超过任何边的容量限制。在这个问题的求解中,Dinic算法和Shortest Augmenting Path (SAP)算法是两种高效的方法。 ...
Dinic算法是一种高效的求解最大流问题的方法,通过构建层次化的残余网络并利用DFS寻找增广路径来不断更新流量,最终找到网络的最大流。通过对算法的深入理解与实践,可以帮助我们在实际问题中更好地应用这一算法。
用DINIC方法实现最大流算法,亲测可以运行!VS2008环境下编辑运行通过!
最大流问题是一个经典的图论问题,它在计算机科学和网络流理论中占有重要地位,尤其在运筹学、算法设计和优化等领域应用广泛。在信息学奥林匹克竞赛中,选手们经常需要解决这类问题来求解网络中的最大传输能力。本文...
【标题】"POJ2195-Going Home" 是一道来自北京大学在线判题系统POJ的编程题目,主要考察的是运用费用流算法解决实际问题的能力。这道题的中文名称是“回家”,通过题目我们可以推测它可能涉及到路径规划或者资源分配...
Dinic算法的基本思路: 1.根据残量网络计算层次图。 2.在层次图中使用DFS进行增广直到不存在增广路 3.重复以上步骤直到无法增广
- POJ3281中,奶牛饮食问题看似复杂,实际上可以通过构建源点到每种食物,每只奶牛到每种饮料,以及奶牛之间的边,将问题转化为多个二分匹配问题的串联,从而用最大流算法解决。 总的来说,最大流问题是一个强大的...
网络流dinic模板,非本人原创。网络流dinic模板,非本人原创
在ACM(国际大学生程序设计竞赛)中,二分匹配算法是解决某些复杂问题的关键工具。本资料详细探讨了二分图匹配算法及其应用,让我们深入了解一下这个主题。 首先,二分图是一个图,其节点可以分为两个不相交的集合...
### 非递归邻接表DINIC最大流算法详解 #### 一、引言 在图论中,寻找网络中的最大流量是一项经典问题。其中,DINIC算法(由Yefim Dinitz于1970年提出)是一种高效解决这类问题的方法。本文将详细介绍一个非递归版本...
Dinic算法,又称为 Dinic's algorithm,是由苏联计算机科学家E. M. Dinic在1970年提出的一种求解网络流问题的高效算法。网络流问题是在图论中的一种经典问题,其目标是确定在一个有向图中,从源点到汇点的最大流量。...
Dinic于1970年提出,是一种求解网络最大流问题的高效算法。在图论和运筹学中,网络流问题涉及到在一个有向图中从一个源节点到一个汇点传输“流量”,同时满足容量限制和供需平衡的条件。Dinic算法以其优秀的性能和...