首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >「R」自己动手进行R基础绘图

「R」自己动手进行R基础绘图

作者头像
王诗翔呀
发布于 2022-12-30 12:24:44
发布于 2022-12-30 12:24:44
1.1K00
代码可运行
举报
文章被收录于专栏:优雅R优雅R
运行总次数:0
代码可运行

原文:https://web.archive.org/web/20210815221329/http://karolis.koncevicius.lt/posts/r_base_plotting_without_wrappers/

基本绘图和R本身一样古老,但对大多数用户来说,它仍然是神秘的。他们可能使用plot(),甚至知道其参数的完整列表,但大多数人从未完全理解它。本文试图通过为外行提供友好的介绍来揭开基础图形的神秘面纱。

相关阅读:

「R」传统图形绘制

「R」R 的基本图形绘制

「R」ggplot2数据可视化

解构一个图

在学习R之后,用户可以很快开始通过调用plot()hist()barplot()生成各种图形。然后,当面对一个复杂的图形时,他们开始使用各种方法,如add=TRUEann=FALSEcex=0,将这些绘制堆叠在一起。对于大多数人来说,这标志着他们基本的绘图旅程的结束,给他们留下的印象是,这是一个需要学习和记住的特殊技巧,但否则就很难、不一致和不直观。如今,即使是撰写基本图形或将其与其他系统进行比较的专家也持有相同的观点。然而,每个人都在使用的那些初始函数只是完成所有工作的较小函数的包装。许多人会惊讶地发现,在底层基础绘图遵循一组小函数的范式,每个函数做一件事,并与另一个函数很好地协作。

让我们从一个最简单的例子开始:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot(0:10, 0:10, xlab = "x-axis", ylab = "y-axis", main = "my plot")

上面的plot()函数实际上只是一个包装器,它调用较低级函数的列表。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot.new()
plot.window(xlim = c(0,10), ylim = c(0,10))
points(0:10, 0:10)
axis(1)
axis(2)
box()
title(xlab = "x-axis")
title(ylab = "y-axis")
title(main = "my plot")

这样写,构成绘图的所有元素就变得清晰了。每个新函数调用都在此之前生成的绘图上绘制单个对象。为了改变图上的某些内容,我们可以很容易地看到应该修改哪条线。作为一个例子,让我们通过以下方式来修改上面的绘图:1)添加网格,2)移除绘图周围的方框,3)移除轴线,4)将轴线标签加粗,5)将注释标签变为红色,6)将标题向左移动。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot.new()
plot.window(xlim = c(0,10), ylim = c(0,10))
grid()
points(0:10, 0:10)
axis(1, lwd = 0, font.axis=2)
axis(2, lwd = 0, font.axis=2)
title(xlab = "x-axis", col.lab = "red3")
title(ylab = "y-axis", col.lab = "red3")
title(main = "my plot", col.main = "red3", adj = 0)

在每种情况下,为了达到想要的效果,只需要修改一行即可。函数名很直观。一个没有任何R经验的人能够轻松地说出哪条线添加了哪个元素或改变了某些参数。 因此,为了构造一个图,我们逐一调用各种函数。但是我们从哪里得到这些函数的名字呢?我们需要记住几百个吗?事实证明,你在一个plot中可能需要做的所有事情都是非常有限的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
par()          # 指定多个绘图参数
plot.new()     # 开始一个新的图形
plot.window()  # 添加坐标系统到绘图区域

points()       # 绘制点
lines()        # 绘制线连接两个点
abline()       # 绘制贯穿图像的无限长线条
arrows()       # 绘制箭头
segments()     # 绘制线段
rect()         # 绘制矩形
polygon()      # 绘制复杂多边形

text()         # 在图形中添加文本
mtext()        # 在图的边缘添加文本

title()        # 图形和轴注释
axis()         # 添加轴
box()          # 添加边框
grid()         # 在坐标系统上添加网格
legend()       # 添加图例

上面的列表涵盖了重建几乎任何绘图所需的大部分功能。作为演示,可以使用example()快速查看每个函数的功能,例如example(rect)。R还有其他一些有用的函数,如rug()jitter(),以简化某些情况,但它们不是关键的,可以使用上面列出的函数实现。

函数名很简单,但是它们的参数呢?事实上,有些参数名,如cex,可能看起来相当含糊。但是参数名称总是图形某个属性的缩写。例如,col是“颜色”的缩写,lwd表示“行宽”,cex表示“字符扩展”(character expansion)。好消息是,在所有的base R函数中,相同的参数代表相同的性质。对于特定的函数help()总是可以用于获取所有参数及其描述的列表。

为了进一步说明参数之间的一致性,让我们回到第一个例子。现在应该很清楚了,只有一个例外axis(1)axis(2)那两行。这些数字12从何而来?这些数字指定了图形周围的位置,它们从1开始,它指的是图形的底部,顺时针向上到4,它指的是右边。下图展示了数字和四边之间的关系。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot.new()
box()
mtext("1", side = 1, col = "red3")
mtext("2", side = 2, col = "red3")
mtext("3", side = 3, col = "red3")
mtext("4", side = 4, col = "red3")

在各种不同的函数中使用相同的位置编号。当某个函数的参数需要指定边时,很可能会使用上面描述的数值表示法。下面是一些例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
par(mar = c(0,0,4,4))        # 图的边距 c(bottom, left, right , top)
par(oma = c(1,1,1,1))        # 图的外边距
axis(3)                      # 显示轴的边
text(x, y, "text", pos = 3)  # pos 选择“文本”显示的位置
mtext("text", side = 4)      # side 指定将在右边显示“文本”

另一个重要的点是向量化。基本绘图函数的几乎所有参数都是向量化的。例如,在绘制矩形时,用户不必在一个循环内逐个添加每个矩形的每个点。相反,他或她可以用一个函数调用绘制所有相关的对象,同时为每个对象指定不同的位置和参数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot.new()
plot.window(xlim = c(0,3), ylim = c(0,3))

rect(xleft = c(0,1,2), ybottom = c(0,1,2), xright = c(1,2,3), ytop = c(1,2,3),
     border = c("pink","red","darkred"), lwd = 10
     )

这是另一个产生棋盘图案的例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot.new()
plot.window(xlim = c(0,10), ylim = c(0,10))

xs <- rep(1:9, each = 9)
ys <- rep(1:9)

rect(xs-0.5, ys-0.5, xs+0.5, ys+0.5, col = c("white","darkgrey"))

构造一个图

基本R图形的优势之一是它的灵活性和定制的潜力。当用户需要遵循在现有示例或模板中找到的特定样式时,它真的很闪耀。下面的一些插图展示了不同的base函数如何协同工作,以及如何从零开始重建各种类型的常见图形。

  • 美国人口随时间增长的图示。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x <- time(uspop)
y <- uspop

plot.new()
plot.window(xlim = range(x), ylim = range(pretty(y)))

rect(x-4, 0, x+4, y)
text(x, y, y, pos = 3, col = "red3", cex = 0.7)

mtext(x, 1, at = x, las = 2, cex = 0.7, font = 2)
axis(2, lwd = 0, las = 2, cex.axis = 0.7, font.axis = 2)
title("US population growth", adj = 0, col.main = "red2")

在这种情况下,每个矩形必须指定四组点:左下角x、y坐标,右上角x、y坐标。最后,即使这是一个更复杂的示例,我们仍然使用对rect()text()mtext()的单个函数调用添加了所有不同的信息。

  • 平行坐标图(使用“iris”数据集)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
palette(c("cornflowerblue", "red3", "orange"))

plot.new()
plot.window(xlim = c(1,4), ylim = range(iris[,-5]))
grid(nx = NA, ny = NULL)
abline(v = 1:4, col = "grey", lwd = 5, lty = "dotted")

matlines(t(iris[,-5]), col = iris$Species, lty = 1)

axis(2, lwd = 0, las = 2)
mtext(variable.names(iris)[-5], 3, at = 1:4, line = 1, col = "darkgrey")

legend(x = 1, y = 2, legend = unique(iris$Species), col = unique(iris$Species),
       lwd = 3, bty = 'n')

在本例中,我们使用了一个特殊的函数matlines(),该函数为矩阵中的每一列绘制一行。到目前为止,我们还做了其他一些新颖的事情:通过palette()更改默认的颜色配置,并在matlines()legend()中使用因子级别指定实际的颜色。改变调色板允许我们定制配色方案,而为颜色参数传递因子可以确保在所有不同的函数中,相同的颜色被一致地分配给相同的因子级别。

  • 1940年弗吉尼亚州的死亡率点图。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
colors <- hcl.colors(5, "Zissou")
ys     <- c(1.25, 2, 1.5, 2.25)

plot.new()
plot.window(xlim = range(0,VADeaths), ylim = c(1,2.75))

abline(h = ys, col = "grey", lty = "dotted", lwd = 3)
points(VADeaths, ys[col(VADeaths)], col = colors, pch = 19, cex = 2.5)
text(0, ys, colnames(VADeaths), adj = c(0.25,-1), col = "lightslategrey")

axis(1, lwd = 0, font = 2)
title("deaths per 1000 in 1940 Virginia stratified by age, gender, and location")

legend("top", legend = rownames(VADeaths), col = colors, pch = 19, horiz = TRUE,
       bty = "n", title = "age bins")

在这个图表中,组按性别、年龄和位置分层。每组的y轴高度都是手动选择的。

  • 使用“mtcars”数据集的双坐标图。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
par(mar = c(4,4,4,4))
plot.new()

plot.window(xlim = range(mtcars$disp), ylim = range(pretty(mtcars$mpg)))

points(mtcars$disp, mtcars$mpg, col = "darkorange2", pch = 19, cex = 1.5)
axis(2, col.axis = "darkorange2", lwd = 2, las = 2)
mtext("miles per gallon", 2, col = "darkorange2", font = 2, line = 3)

plot.window(xlim = range(mtcars$disp), ylim = range(pretty(mtcars$hp)))

points(mtcars$disp, mtcars$hp, col = "forestgreen", pch = 19, cex = 1.5)
axis(4, col.axis = "forestgreen", lwd = 2, las = 2)
mtext("horse power", 4, col = "forestgreen", font = 2, line = 3)

box()
axis(1)
mtext("displacement", 1, font = 2, line = 3)
title("displacement VS mpg VS hp", adj = 0, cex.main = 1)

在这里,我们在一个图形上可视化了两个散点图,具有不同的y轴。这里的技巧是使用plot.window()更改图形中间的坐标系统。但是请注意,双y轴的绘图是不可取的,所以不要把这个例子作为一个建议。

  • 显示不同饲料类型鸡体重分层分布的脊线密度图。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dens <- tapply(chickwts$weight, chickwts$feed, density)

xs <- Map(getElement, dens, "x")
ys <- Map(getElement, dens, "y")
ys <- Map(function(x) (x-min(x)) / max(x-min(x)) * 1.5, ys)
ys <- Map(`+`, ys, length(ys):1)

plot.new()
plot.window(xlim = range(xs), ylim = c(1,length(ys)+1.5))
abline(h = length(ys):1, col = "grey")

Map(polygon, xs, ys, col = hcl.colors(length(ys), "Zissou", alpha = 0.8))

axis(1, tck = -0.01)
mtext(names(dens), 2, at = length(ys):1, las = 2, padj = 0)
title("Chicken weights", adj = 0, cex = 0.8)

在本例中,通过将y值转换为0 - 1.5的范围,然后为每种馈线类型添加不同的偏移量,来完成准备密度的大部分工作。为了使绘制的密度很好地重叠,我们从顶部开始绘制它们,然后向下。之后Map()polygon()完成所有工作。

  • 鸡重量与饲料类型的小提琴图
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dens <- tapply(chickwts$weight, chickwts$feed, density)
cols <- hcl.colors(length(dens), "Zissou")

xs <- Map(getElement, dens, "y")
ys <- Map(getElement, dens, "x")

xs <- Map(c, xs, Map(rev, Map(`*`, -1, xs)))
ys <- Map(c, ys, Map(rev, ys))

xs <- Map(function(x) (x-min(x)) / max(x-min(x) * 1.1), xs)
xs <- Map(`+`, xs, 1:length(xs))


plot.new()
plot.window(xlim = range(xs), ylim = range(ys))
grid(nx = NA, ny = NULL, lwd = 2)

Map(polygon, xs, ys, col = cols)

axis(2, las = 1, lwd = 0)
title("Chicken weight by feed type", font = 2)

legend("top", legend = names(dens), fill = cols, ncol = 3, inset = c(0, 1),
       xpd = TRUE, bty = "n")

现在多边形是双面的,所以我们需要镜像和复制xs和ys。在上面的代码中,第5行和第6行完成了这项工作。之后的绘图几乎与前面的示例相同。在图例上还有一个额外的技巧,我们使用“inset”将它推到另一边。

  • 使用来自“mtcars”数据集的变量的相关矩阵图。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cors <- cor(mtcars)
cols <- hcl.colors(200, "RdBu")[round((cors+1)*100)]

par(mar = c(5,5,0,0))
plot.new()
plot.window(xlim = c(0,ncol(cors)), ylim = c(0,ncol(cors)))

rect(row(cors)-1, col(cors)-1, row(cors), col(cors))
symbols(row(cors)-0.5, col(cors)-0.5, circles = as.numeric(abs(cors))/2,
        inches = FALSE, asp = 1, add = TRUE, bg = cols
       )

mtext(rownames(cors), 1, at=1:ncol(cors)-0.5, las=2)
mtext(colnames(cors), 2, at=1:nrow(cors)-0.5, las=2)

这里的第二行通过将相关性范围从-1:1转换为0:200为每个相关值分配颜色。然后我们使用rect()函数获得网格,并使用symbols()添加具有指定半径的圆。得到的图类似于corrplot library实现的图。

总结

R基础绘图系统有几个抛光和易于使用的包装器,有时很方便,但从长远来看只会混淆和隐藏东西。因此,大多数R用户从来没有被正确地介绍过基本绘图范式背后的真正功能,并被其许多感知到的特性所迷惑。然而,如果检查得当,基本绘图可以变得强大、灵活和直观。在所有包装的引擎盖下,繁重的搬运工作是由一组相互配合的简单功能完成的。通常只需要几行代码就可以生成一个优雅的定制图形。


参考:

  1. “Why I don't use ggplot2” by Jeff Leek ↩︎
  2. “Why I use ggplot2” by David Robinson ↩︎
  3. “Graphics parameter mnemonics” by Paul Murrell ↩︎
  4. “Reproducing the style of a histogram plot in R” on stackoverflow.com ↩︎
  5. answer about plotting the legend in the margins with base R on stackoverflow.com ↩︎
  6. “corrplot” package on CRAN [ ↩︎](
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 优雅R 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
洛谷P4016 负载平衡问题(最小费用最大流)
题目描述 GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 nn 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。 输入输出格式 输入格式: 文件的第 11 行中有 11 个正整数 nn ,表示有 nn 个仓库。 第 22 行中有 nn 个正整数,表示 nn 个仓库的库存量。 输出格式: 输出最少搬运量。 输入输出样例 输入样例#1:  5 17 9 14 16 4 输出样例#1:  11 说明 1 \leq n \leq 1001≤n≤10
attack
2018/04/10
8070
洛谷P4014 分配问题(费用流)
题目描述 有 nn 件工作要分配给 nn 个人做。第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij​ 。试设计一个将 nn 件工作分配给 nn 个人做的分配方案,使产生的总效益最大。 输入输出格式 输入格式: 文件的第 11 行有 11 个正整数 nn ,表示有 nn 件工作要分配给 nn 个人做。 接下来的 nn 行中,每行有 nn 个整数 c_{ij}cij​ ​​,表示第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij​ 。 输出格式: 两行分别输出最小总效益和最大总效益
attack
2018/04/10
7450
洛谷P4013 数字梯形问题(费用流)
梯形的第一行有 mmm 个数字。从梯形的顶部的 mmm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。
attack
2018/07/27
3300
洛谷P4013 数字梯形问题(费用流)
洛谷P4015 运输问题(费用流)
题目描述 WW 公司有 mm 个仓库和 nn 个零售商店。第 ii 个仓库有 a_iai​ 个单位的货物;第 jj 个零售商店需要 b_jbj​ 个单位的货物。 货物供需平衡,即\sum\limits_{i=1}^{m}a_i=\sum\limits_{j=1}^{n}b_ji=1∑m​ai​=j=1∑n​bj​ 。 从第 ii 个仓库运送每单位货物到第 jj 个零售商店的费用为 c_{ij}cij​ ​​ 。 试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。 输入输出格式 输入格式:
attack
2018/04/10
7970
洛谷P3357 最长k可重线段集问题(费用流)
题目描述http://www.cnblogs.com/zwfymqz/p/8559566.html 给定平面 x-O-yx−O−y 上 nn 个开线段组成的集合 II ,和一个正整数 kk 。试设计一个算法,从开线段集合 II 中选取出开线段集合 S\subseteq IS⊆I ,使得在 xx 轴上的任何一点 pp ,SS 中与直线 x=px=p 相交的开线段个数不超过 kk ,且\sum\limits_{z\in S}|z|z∈S∑​∣z∣ 达到最大。这样的集合 SS 称为开线段集合 II 的最长 kk 
attack
2018/04/10
8430
洛谷P3358 最长k可重区间集问题(费用流)
题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度。 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区
attack
2018/04/10
8770
洛谷P3358 最长k可重区间集问题(费用流)
洛谷P3356 火星探险问题(费用流)
题目描述 火星探险队的登陆舱将在火星表面着陆,登陆舱内有多部障碍物探测车。登陆舱着陆后,探测车将离开登陆舱向先期到达的传送器方向移动。探测车在移动中还必须采集岩石标本。每一块岩石标本由最先遇到它的探测车完成采集。每块岩石标本只能被采集一次。岩石标本被采集后,其他探测车可以从原来岩石标本所在处通过。探测车不能通过有障碍的地面。本题限定探测车只能从登陆处沿着向南或向东的方向朝传送器移动,而且多个探测车可以在同一时间占据同一位置。如果某个探测车在到达传送器以前不能继续前进,则该车所采集的岩石标本将全部损失。 用一
attack
2018/04/10
6740
洛谷P4012 深海机器人问题(费用流)
题目描述 深海资源考察探险队的潜艇将到达深海的海底进行科学考察。 潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。 深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。 每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。 本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。 用一个 P\times QP×Q 网格表示深海机器人的可移动位置。西南角的坐标为 (0,0)
attack
2018/04/10
6530
洛谷P4012 深海机器人问题(费用流)
洛谷P2770 航空路线问题(费用流)
为了满足流量的限制,肯定会想到拆点,把每个点拆为两个,连流量为$1$,费用为$1$的边
attack
2018/07/27
3660
洛谷P2045 方格取数加强版(费用流)
对于拆出来的每个点,在其中连两条边,一条为费用为点权,流量为1,另一条费用为0,流量为INF
attack
2019/03/05
3650
洛谷P2774 方格取数问题(最小割)
题意 $n \times m$的矩阵,不能取相邻的元素,问最大能取多少 Sol 首先补集转化一下:最大权值 = sum - 使图不连通的最小权值 进行黑白染色 从S向黑点连权值为点权的边 从白点向T连权值为点券的边 黑点向白点连权值为INF的边 这样就转化成了最小割问题,跑Dinic即可 /* 首先补集转化一下:最大权值 = sum - 使图不连通的最小权值 进行黑白染色 从S向黑点连权值为点权的边 从白点向T连权值为点券的边 黑点向白点连权值为INF的边 跑Dinic */ #include<cstdio
attack
2018/07/27
5340
BZOJ4819: [Sdoi2017]新生舞会(01分数规划)
Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴。Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出  a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度。Cathy还需要考虑两个人一起跳舞是否方便, 比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度。当然, 还需要考虑很多其他问题。Cathy想先用一个
attack
2018/04/10
7480
洛谷P2891 [USACO07OPEN]吃饭Dining
题目描述 Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not
attack
2018/04/11
8050
洛谷P2891 [USACO07OPEN]吃饭Dining
洛谷P4926 [1007]倍杀测量者(差分约束)
题意 题目链接 Sol 题目中的两个限制条件xian \[A_i \geqslant (K_i - T)B_i\] \[A_i(K_i + T) \geq B_i\] 我们需要让这两个至少有一个不满足 直接差分约束建边即可 这里要用到两个trick 若某个变量有固定取值的时候我们可以构造两个等式\(C_i - 0 \leqslant X, C_i - 0 \geqslant X\)。 乘法的大小判断可以取log变加法,因为\(y = log(x)\)也是个单调函数 #include<bits/stdc++.
attack
2019/03/12
4390
BZOJ4514: [Sdoi2016]数字配对(费用流)
Description 有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。 若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值。 一个数字只能参与一次配对,可以不参与配对。 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。 Input 第一行一个整数 n。 第二行 n 个整数 a1、a2、……、an。 第三行 n 个整数 b1、b2、……、bn。 第四行 n 个整数 c1、c2、……、cn。 O
attack
2018/04/03
1.1K0
洛谷P2598 [ZJOI2009]狼和羊的故事
题目描述 “狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变
attack
2018/04/11
6170
洛谷P4174 [NOI2006]最大获利
题目描述 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究、站址勘测、最优化等项目。 在前期市场调查和站址勘测之后,公司得到了一共 N 个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第 i个通讯中转站需要的成本为  (1≤i≤N)。 另外公司调查得
attack
2018/04/11
7000
LOJ#505. 「LibreOJ β Round」ZQC 的游戏(最大流)
题意 题目链接 Sol 首先把第一个人能吃掉的食物删掉 然后对每个人预处理出能吃到的食物,直接限流跑最大流就行了 判断一下最后的最大流是否等于重量和 注意一个非常恶心的地方是需要把除1外所有人都吃不到的食物删掉 #include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 10, INF = 1e9 + 10; int sqr(int x) {return x * x;} inline int read() { char c
attack
2019/02/26
4240
洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication
题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流。这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相连,a2与a3相连,等等,那么电脑a1和a(c)就可以互发电邮。 很不幸,有时候奶牛会不小心踩到电脑上,农夫约翰的车也可能碾过电脑,这台倒霉的电脑就会坏掉。这意味着这台电脑不能再发送电邮了,于是与这台电脑相关的连接也就不可用了。 有两头奶牛就想:如果我们两个不能互发电邮,至少需要坏掉多少台电脑呢?请编写一个程序
attack
2018/04/11
8180
洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication
洛谷 P3386 【模板】二分图匹配 Dinic版
题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 输出格式: 共一行,二分图最大匹配 输入输出样例 输入样例#1: 1 1 1 1 1 输出样例#1: 1 说明 n,m \leq 1000n,m≤1000, 1 \leq u \leq n1≤u≤n, 1 \leq v \leq m1≤v≤m 因为数据有坑,可能会遇到 v>mv>m 的情况。请把 v>mv>
attack
2018/04/11
7610
相关推荐
洛谷P4016 负载平衡问题(最小费用最大流)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档