浅谈\rm OI中的画图利器——\rm Graphviz入门
那是什么?
在写题解/博客时,我们有可能遇到需要画有向/无向图、流程图等等,\rm Windows自带的画图又不能满足我们的需求,我们就可以用到\rm Graphviz来画图。
$\rm Graphviz$:是一个开源的软件,其中包含$\rm DOT
如何下载&安装?
进入http://www.graphviz.org/download/
\rm Ubuntu$用户下载$\rm Ubuntu\ packages
\rm Windows$用户下载$\rm Stable\ 2.38\ Windows\ install\ packages \rightarrow \text{graphviz-2.38.zip}
首先,点击“此电脑”->“属性”
![Skip 1](https://cdn.luogu.com.cn/upload/pic/28568.png)
弹出来的窗口左侧“高级系统设置”->“环境变量(N)...”
![Skip 2](https://cdn.luogu.com.cn/upload/pic/28570.png)
上方“xxx的用户变量”->“$\rm Path$”->“编辑(E)...”
![Skip 3](https://cdn.luogu.com.cn/upload/pic/28569.png)
接下来分两种情况:
第一种:在弹出窗口内“变量值”后加上“你的解压后的目录\release\bin;”(注意分号)
![Skip 4(1)](https://cdn.luogu.com.cn/upload/pic/28572.png)
第二种:在弹出窗口内点击“新建”,然后输入“你的解压后的目录\release\bin”然后确定。
![Skip 4(2)](https://cdn.luogu.com.cn/upload/pic/28571.png)
然后,一路点确定下来即可。
如何验证是否完成?
打开命令行(win+R,输入cmd然后回车/shift+右键->在此处打开命令窗口/Linux 终端)输入
```
dot -version
```
![](https://cdn.luogu.com.cn/upload/pic/28573.png)
![](https://cdn.luogu.com.cn/upload/pic/28577.png)
如果没有报错,那么你设置完成
### 如何使用?
(以下操作在$\rm Ubuntu\ 16.04\ LTS$中进行,其他操作系统没有太大差别。
建立一个文件$\rm xxx.dot$。
![](https://cdn.luogu.com.cn/upload/pic/28579.png)
使用纯文本编辑器(如记事本/notepad++/vim/gedit等)编辑。
我们有一个例子来测试它:
```
digraph example{
node[shape=box]
a->b;
b->c;
}
```
(这里,我们使用vim做示范,其它编辑器同理)
![](https://cdn.luogu.com.cn/upload/pic/28583.png)
在同样目录下,打开命令行(或使用```cd```命令),输入
```
dot test.dot -T png -o test.png
```
则会在目录下生成一个文件test.png
![](https://cdn.luogu.com.cn/upload/pic/28586.png)
### 怎么写$\rm DOT$?(DOT入门)
#### 无向图
无向图的格式如下:
```
graph 名字(随意){
无向图的内容
}
```
无向图使用```a--b```的形式来描述边,$\rm dot$会帮你自动调整每个节点的位置。
例如:
```
graph example{
a--b;
a--c;
b--c;
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28587.png)
如果边数太多,我们还可以使用```a->{b;c;d;e}```的方式来描述很多条边,比如:
```
graph example{
a--{b;c;d;e;f;g;h;i};
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28588.png)
如果你还需要不同的形状/颜色,你可以参考以下的例子:
```
graph example{
a--b[color=red;label="233"];
a--c[label="2333"];
b--{d;e};
b[shape=box];
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28589.png)
即边、点后面可以加```[color=xxx]```表示颜色
```[label="xxx"]```表示边权
```[shape=xxx]```表示形状
常用的形状(点)有:
```box,oval,circle,point,egg,triangle,square,record```等,可以到网上去找,这里不一一枚举。
还有一点,若所有的边或点都需要设置,可以使用
```
edge[xxx]
node[xxx]
```
的方式,比如:
```
graph example{
edge[color=red];
node[shape=box];
a--b;
b--c;
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28590.png)
#### 有向图
有向图的格式和无向图基本一样:
```
digraph 名字(随意){
图
}
```
其中边使用```a->b```描述,比如:
```
digraph example{
node[shape=circle];
root[shape=box];
root->{b;e};
b->{c;d};
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28592.png)
#### 进阶&实例
如何指定边射出的方向?
我们通过具体例子来说明:
```
digraph example{
a0:w->b0;//其中w意思是west,支持w,e,n,s,sw,se,nw,ne
a1:e->b1;
a2:n->b2;
a3:s->b3;
a4:nw->b4;
a5:ne->b5;
a6:sw->b6;
a7:se->b7;
}
```
![](https://cdn.luogu.com.cn/upload/pic/28622.png)
如何让修改图片的朝向?
我们把上面的例子做些修改,添加一句```rankdir = LR;```
```
digraph example{
rankdir = LR;
a0:w->b0;//其中w意思是west,支持w,e,n,s,sw,se,nw,ne
a1:e->b1;
a2:n->b2;
a3:s->b3;
a4:nw->b4;
a5:ne->b5;
a6:sw->b6;
a7:se->b7;
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28623.png)
想要”结构体“的效果?
我们以一个链表的例子来理解:
```
digraph example{
rankdir = LR; //让图片横过来
node[shape = record]//record形状是专门用来做类似”结构体“的东西的
a[label = "{A|}"];//每个的'|'都是一列
b[label = "{B|}"];
c[label = "{C|}"];
d[label = "{D|NULL}"];
a->b:w;
b->c:w;
c->d:w;
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28617.png)
我们通过几个例子来熟悉```record```
```
digraph example{
a[shape = record; label = "A|B|C|D"];
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28624.png)
```
digraph example{
a[shape = record; label = "{A|B|C|D}"];
}
```
效果:
![](https://cdn.luogu.com.cn/upload/pic/28625.png)
(注意:```rankdir = LR;```也会影响方向)
---
### 后记
$\rm Graphviz$的功能还有很多,网上也有许多详细的教程,这边只选取一些常用功能进行介绍,再加上本人的水平还很低,所以出错是难免的,希望大家谅解。