随笔分类 -  图论·网络流

摘要:题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条。分析: 求最短路的条数可以用最大流,不过要是去掉原图中不在最短路上的边, 判断某条边是不是最短路上的边的时候,如果满足 d1[from] +d2[to]+ edge[i].w =dis[en] 则可以说明该边是最短路上的边,其中 d1[] 为各点到起点的最短距离,d2[] 为各点到终点的最短距离#include<stdio.h>#include<string.h>#include<stdlib.h>#include<climits>#include&l 阅读全文
posted @ 2012-10-12 19:10 'wind 阅读(977) 评论(0) 推荐(1)
摘要:题意: 有 2*n个同学,n男n女,知道了 有 m 对 男女之间木有吵过架,现在这 n 个女生要找对象,要求没有和她吵过架或者没有和她的一个朋友吵过架, 当 n 个女生都找到对象的时候算作一轮,然后重新找,满足每个女生都不能找和上次一样的对象,而且每个女生除了自己没有吵过架的人外,最多 可一和 k 个男生成为朋友,问最多能进行多少轮。分析: 建图: 将每个女生 i 拆成两个点 i 和 i+n 如果女生 i 可以和 男生 j 没吵过架,就在 i 和 j 之间连一条容量为 1 的边 否则在 i+n 和 j 之间连一条容量为 1 的边 在 i 和 i+n之间连一条容量为 k的边, 在 s 和 1.. 阅读全文
posted @ 2012-10-11 23:34 'wind 阅读(437) 评论(0) 推荐(0)
摘要:题意: 有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di, 每个人要烤的肉可以分成若干份在同时烤,问是否存在一种方案可以满足所有顾客的需求。分析: 将所有的到达时间和结束时间按升序排序,得到 x <= 2n-1 个时间区间。 建图: s为源,t为汇, 每个顾客i作为一个结点并连边(s, i, ni*ti) 每个区间j作为一个结点并连边(j, t, (ej-sj)*M),其中sj, ej分别表示区间j的起始时间和终止时间 对任意顾客i和区间j,若 [sj, ej] 完全包含在 [si 阅读全文
posted @ 2012-10-11 00:53 'wind 阅读(611) 评论(0) 推荐(1)
摘要:题意: 有 n 个地点可以建通讯站,知道了每个地点建立通讯站的费用,有m个需求,每个需求 u,v,c表示如果建立了 u 和 v 通讯站可以获得 c 利润,问建 里那些通讯站可以使得收益最大。分析:将边看成点,求最大权值闭包。#include<stdio.h>#include<string.h>#include<stdlib.h>#include<climits>#define min(a,b)(a)<(b)?(a):(b)const int INF=INT_MAX;const int maxn=60000;const int maxm=20 阅读全文
posted @ 2012-10-06 12:52 'wind 阅读(190) 评论(0) 推荐(0)
摘要:题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙, 每个逮捕队伍在每个城市可以选择抓或不抓,如果抓了 第 i 个城市的犯罪团伙,第 i-1 个城市的犯罪团伙就知道了消息 ,如果第 i-1 的犯罪 团伙之前没有被抓,任务就失败,问要抓到所有的犯罪团伙,派出的队伍需要走的最短路是多少。 分析: 最小费用最大流,需要注意的地方在于怎么去保证每个每个城市的团伙仅仅被抓一次,且在抓他之前,第i-1城市的团伙已经被抓。 方法是把拆点后的城市 i 和 i`之间的费用要设成一个很小的负值,这样可以保证该城市一 阅读全文
posted @ 2012-09-24 19:59 'wind 阅读(679) 评论(0) 推荐(0)
摘要:题意: 有n个城市,有个小偷想从其中一个城市逃到另一个城市,警察想要堵截这个小偷,知道了在每个城市堵截的成本,问如何安排在哪些城市堵截可以使得 小偷一定会被抓住,而且成本最低。分析: 最小割模型,城市有成本限制,需要差点来限制,具体建图方法: 将每个城市 i 拆成两个点 i 和 i + n, 之间连一条容量为该点花费的边,如果 城市 a 和 b 连通,则在 a+n 和 b, b+n 和 a 之间连一条容量为无穷的的边, 这样可以保证最大流量即花费仅受到顶点容量的限制, 如果 起点为 S ,终点为 D ,求出 点S 到 点 D+n 的最大流即为满足条件的最小割。#include<stdio 阅读全文
posted @ 2012-09-18 09:08 'wind 阅读(236) 评论(0) 推荐(0)
摘要:题意: 有 F种食物和D种饮料,知道了每种食物和饮料的数量,有n 个人,知道了这些人分别喜欢的食物和饮料,当每个人能够吃到自己喜欢的一个食物和喝到自己喜欢 的一种饮料,他就会开心,问最多能有多少人可以开心。分析:在 源点 和 每种食物之间 连一条边,容量为 食物的数量,将每头牛拆成两个点,将每头牛的第一个点和第二个点之间连一条容量为 1 的边,在每头牛喜欢的食物和该牛的第一个点之间连一条容量为 1 的边,在每头牛喜欢的饮料和该牛的第二个点之间连一条容量为 1 的边,在 汇点 和每种饮料之间连一条容量为饮料数量 的边,求最大流。#include<stdio.h>#include< 阅读全文
posted @ 2012-09-16 18:26 'wind 阅读(267) 评论(0) 推荐(0)
摘要:题意: 有n 个金矿,每个金矿开发需要一定的价值,开发之后可以获得一定的价值,而且一些金矿受到另一些金矿的限制,即开采这个金矿之前要开采 限制它的金矿,问最多可以获得多少价值。分析: 比较明显的最大闭合权图。 建图:如果某个金矿的开发利润为正值,就在源点和该点之间连一条容量为该利润的边 如果某个金矿的开发利润为负值,就在该点和汇点之间连一条容量为该利润绝对值的边 如果某个金矿收到另一个金矿的限制,就在两个金矿之间连一条容量为INF的边。 累计所有正值利润的和 sum,获得的最大利润为sum - maxflow#include<stdio.h>#include<string.h 阅读全文
posted @ 2012-09-11 17:36 'wind 阅读(232) 评论(0) 推荐(0)
摘要:题意: 求最大流。分析: 用书上的模版各种超时,需要预处理好距离。#include<stdio.h>#include<string.h>#include<stdlib.h>#include<climits>#define min(a,b)(a)<(b)?(a):(b)const int INF=INT_MAX;const int maxn=100005;const int maxm=200005;struct node{ int from,to,next,c;}e[maxm];int tot;int head[maxn];void add( 阅读全文
posted @ 2012-09-09 20:39 'wind 阅读(315) 评论(0) 推荐(0)
摘要:题意:有 n 个鸟,知道了每只鸟的活动半径和每个鸟窝在一开的时候有的草的数量,有m 个草堆,每个草堆有一定数量的草,知道了每个草堆的位置, 所有能被鸟捡到即被鸟覆盖到地方的草到最后都会被捡完,问是否存在一种情况使得所有鸟最后拥有的草的数量不超过第一只鸟用有的草的数量。分析: 首先让第一只鸟将可以捡到的草全部捡完,这时候拥有的草的数量为第一只鸟最后所能拥有的最多的草的数量记为k,限制其他鸟可以拥有的 草的数量不超过 k,看最后这些鸟能否将能捡的草捡完。 建图: 源点 s=0,汇点 t=(n-1)+m+1 鸟的编号1..n-1,草堆编号n..n+m-1 在源点和每只鸟之间连一条边容量设为 k, 如 阅读全文
posted @ 2012-09-01 14:25 'wind 阅读(232) 评论(0) 推荐(0)
摘要:题意: 给出有n 个节点的网络,和m条单向边,知道了每条边的容量,问哪些边满足增加该边的容量后,能使得从起点到终点的总流量增加(只能修改一条边!)。分析:如果某条边是该关键边,首先满足该边一定能满流,其次要有从 s 到 t 经过该边的可行路径。 先求最大流,找出割边,在正向网络上从 s 开始深搜,将遍历到点用v1[]标记,在反向网络上从 t 深搜,将遍历到的点用v2[]标记, 如果某条边满足 e[i].cap=e[i].flow且v1[e[i].from]=1,e[e[i].to]=1,那么该边即为要求的关键边。#include<stdio.h>#include<string 阅读全文
posted @ 2012-08-24 23:10 'wind 阅读(200) 评论(0) 推荐(0)
摘要:题意: 一群伞兵要降落在一个m*n的区域,知道了每个伞兵落入的位置,防守方可以在任意一排或任意一列安装武器,分别可以防御某一排或某一列的敌人,知道了武器放 某一排或某一列的建造费用,找出一种建造方案使得所有武器花费的乘以最小并足以防御任意一个位置的敌人。分析:建图方式:将每一行看成一个点(1..n),将每一列看成一个点(n..n+m)建立一个源点 s = 0, 汇点 t = n+m+1 在 s 和每个行顶点之间连一条容量为行造价的边 在每个列顶点和 t 之间连一条容量为列造价的边 如果(x,y)位置有伞兵,就在 x 行和y列之间连一条容量为无穷大的边 求出最小割即为最小费用,需要注意的地方是要 阅读全文
posted @ 2012-08-23 23:35 'wind 阅读(200) 评论(0) 推荐(0)
摘要:题意: 给出一个 n*m的矩阵,知道了每一行元素的和(n个),每一列元素的和(m个) 给出t个条件: a b c d 表示 a b 和 数字 d 满足条件 c分析: 此题的最大流有下界的限制,用上下界最大流求解时,需要先去掉下界,判断是否存在可行流将 1 到 n 行每行看作一个节点(1..n),将 1 到 m 列每列看作一个节点(n+1..n+m) 建立源点 s=0,汇点 t=n+m+1 在源点 s 和每一个行节点之间连一条上界是行数字的和下界为 0的边在每一个列节点和和汇点t之间连一条上界是列数字的和下界为 0的边 如果 i 行 j 列的数字大于 x,就在 i 行节点和 j 列节点之间... 阅读全文
posted @ 2012-08-22 19:28 'wind 阅读(320) 评论(0) 推荐(0)
摘要:题意:给定带点权的有向无环图,求最大权闭合图权值,同时要使得选取的点数最小分析:建图: 建立源点 s=0,在 s 和 正权点之间连一条边权为该点值的边 建立汇点 t=n+1 在 负权点 和 t 之间连一条边权点为该点的绝对值的边 输入的边权值设为INF,求最大流,求最大流后,在残留网络中从s出发dfs能搜到点都为最大权闭合图中的点, 即这个最小割对应的是最大权闭合图然后让正权点值的累加和减去最大流 就是闭合图的最大权。#include<stdio.h>#include<string.h>#include<stdlib.h>#define clr(x)mems 阅读全文
posted @ 2012-08-21 00:22 'wind 阅读(215) 评论(0) 推荐(0)
摘要:题意:有 M 个猪圈,每个猪圈里初始时有若干头猪,一开始所有猪圈都是关闭的,依次来了 N 个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪, 每个顾客分别都有他能够买的数量的上限,每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。分析:此题建图关键在于合并猪圈 建图: 对于每个猪圈的第一个顾客,从源点向他连一条边,容量就是该猪圈里的猪的初始数量 如果从源点到一名顾客有多条边,则可以把它们合并成一条,容量相加, 对于每个猪圈,假设有 n 个顾客打开过它,则对所有整数 i ∈ [1, n),从该猪圈的第 i 个顾客向第 i + 1 个顾客连一 阅读全文
posted @ 2012-08-15 13:34 'wind 阅读(235) 评论(0) 推荐(0)
摘要:题意: 已知有 N 个牛棚,且每个牛棚在一开始的时候有一定数量的牛,每个牛棚可以用来让牛避雨,但容量都有一定的限制,知道了一些牛棚之间的道路长度,问使得下雨时使所有牛都可以找到地方躲雨,且要使得所有牛中走过的路中的最大值尽可能小,并求出该最大值分析: 建图:将每个牛棚拆成两个点v,v` 建立一个源点 s =0 , 在 s 和每个点 i 之间连一条容量大小为该牛棚初始牛数量的边, 建立一个汇点 t =2*n+1 在 每个点 i+n 和 t 之间连一条容量大小为该牛棚容量的边。 如果点 u 和 v 满足条件,就在 u 和 v +n ,v 和 u+n之间连一条容量大小为 INF 的边。 如果最大流 阅读全文
posted @ 2012-08-14 17:10 'wind 阅读(215) 评论(0) 推荐(0)
摘要:题意: 给出一个 n*n的数字矩阵,从左上角走到右下角每次只能向下或向右走,且每个格子中的数字只能取一次,问走k次之后可以取到的最大的数值和为多少。分析: 比较经典的网络流解DP的题目,可以用费用流求解, 建图: 将每个割格点拆分成两个点 v(入点),v`(出点),在v 和v`之间先连一条容量为 1 ,费用为格子数值的边,再连一条容量为无穷大费用为0的边, 这样既可以保证每个数只被取一次,又能保证可以多次经过这个数所在的格子 建立源点 s = 0,在 s 和 最左上角的格子的入点之间连一条容量为 K,费用为0 的边 建立汇点 t = n*n*2+1,在 t 和最右下角的格子的出点之间连一条容量 阅读全文
posted @ 2012-08-13 15:13 'wind 阅读(277) 评论(0) 推荐(0)
摘要:题意: 有一个有 N 个节点M 条边的的有向图,每个点对应两种操作: 将该点所有入边删除 ‘+’ ,对应一个花费,将该点所有出边删除 ‘ - ’亦对应一个花费 问如何操作将所有边删除使得花费的总和最小。分析: 建图: 将每个点拆分成两个点, i(左点) 和 i+n(右点) , 建立一个源点 s=0,汇点 u=2*n+1在源点和每个点左面的点连一条边,容量为删除出边的费用 在汇点和每个点右面的点连一条边,容量为删除入边的费用如果有 u到 v 的边,在u 和 v +n 之间连一条边,容量为无穷大 求出最大流即最小割 从源点深搜找出残流不为 0 的点,把这些点标记掉,剩下的为标记的点即为删除的顶点。 阅读全文
posted @ 2012-08-11 19:05 'wind 阅读(276) 评论(0) 推荐(0)
摘要:题意: 有一个有 N 个节点的无向图,要求找出两条从1 节点 到 n 节点两条最短且不同的路径,求出其长度和。分析: 由于是两条不同的路径,可以用最小费用最大流,因为是有重边,所以要用邻接表存储边。 建图:建立一个源点 s = 0 在 s 和 1 节点之间加一条容量为 2 费用为 0 的边, 建立一个汇点 u = n+1 在 n 和 u 之间加一条容量为 2 费用为 0 的边, 两两节点如果连通,就在之间加一条 容量为 1,费用为边的长度的双向边。#include<stdio.h>#include<string.h>#define clr(x)memset(x,0,si 阅读全文
posted @ 2012-08-11 12:38 'wind 阅读(242) 评论(0) 推荐(0)
摘要:题意 : 已知有n 个浮冰 ,和每个企鹅可以跳跃的最大距离,知道了每个浮冰的坐标,和该浮冰上一开始有的企鹅数量,和 该浮冰最多能承受的跳跃次数,跳跃次数是指从该浮冰跳出的最大次数,浮冰的编号从 0 开始,里面哪些浮冰满足 最后所有的企鹅都能够到达。分析: 建立一个超级 源点 s=0 ,将每个浮冰分成两个点,左边的点记为 1..n ,右面的点依次为 n+1..n+n,在浮冰 i 和 i+n 之间连一条从i 到 i+n的边,容量设为 浮冰 i 上的 最大跳跃次数,在源点 s 和 每块冰 i(1..n)之间连一条从s 到 i 的边,容量设为冰 i 上初始的企鹅数量,即为该点的初始流量,如果 冰 i 阅读全文
posted @ 2012-08-05 20:26 'wind 阅读(278) 评论(0) 推荐(0)