题外话
我们这回学了图,老师让我们写一篇关于图的读入的博客
讲真的,我不知道老师为什么要让我们写这种东西,明明连题目的五个字都凑不到
咳咳,请忽略以上内容,接下来开始正题:
图的基本概念
以下内容来自百度百科:
图的简介
在数学中,图是描述于一组对象的结构,其中某些对象对在某种意义上是相关的。这些对象对应于称为顶点的数学抽象(也称为节点或点),并且每个相关的顶点对都称为边(也称为链接或线)。通常,图形以图解形式描绘为顶点的一组点或环,并通过边的线或曲线连接。 图形是离散数学的研究对象之一。
图的定义
图主要有以下两种定义。
二元组的定义
图 G G G是一个有序二元组 ( V , E ) (V,E) (V,E),其中 V V V称为顶集(Vertices Set), E E E称为边集(Edges set), E E E与 V V V不相交。它们亦可写成 V ( G ) V(G) V(G)和 E ( G ) E(G) E(G)。其中,顶集的元素被称为顶点(Vertex),边集的元素被称为边(edge)。
E的元素都是二元组,用 ( x , y ) (x,y) (x,y)表示,其中 x , y ∈ V x,y\in V x,y∈V。
三元组的定义
图 G G G是指一个三元组 ( V , E , I ) (V,E,I) (V,E,I),其中 V V V称为顶集, E E E称为边集, E E E与 V V V不相交; I I I称为关联函数, I I I将 E E E中的每一个元素映射到 V × V V×V V×V。如果 e e e被映射到 ( u , v ) (u,v) (u,v),那么称边 e e e连接顶点 u , v u,v u,v,而 u , v u,v u,v则称作 e e e的端点, u , v u,v u,v此时关于 e e e相邻。同时,若两条边 i , j i,j i,j有一个公共顶点 u u u,则称 i , j i,j i,j关于 u u u相邻。
图的分类
有向图、无向图
如果给图的每条边规定一个方向,那么得到的图称为有向图。在有向图中,与一个节点相关联的边有出边和入边之分。相反,边没有方向的图称为无向图。
完全图
完全图是一个简单的无向图,其中每对不同的顶点之间都恰连有一条边相连。完整的有向图又是一个有向图,其中每对不同的顶点通过一对唯一的边缘(每个方向一个)连接。 n n n个端点的完全图有n个端点以及 n ( n − 1 ) / 2 n(n − 1) / 2 n(n−1)/2条边,以 K n K_n Kn表示。它是 ( k − 1 ) (k − 1) (k−1)正则图。所有完全图都是它本身的团(clique)。
有权图与无权图
如果图中的边有各自的权重,得到的图是有权图。比如地铁路线图,连接两站的边的权重可以是距离,也可以是价格,或者其他。反之,如果图的边没有权重,或者权重都一样(即没有区分),称为无权图。
连通图
如果图中任意两点都是连通的,那么图被称作连通图。图的连通性是图的基本性质。无向图中的一个极大连通子图称为其的一个连通分量。有向图中,如果对任意两个顶点 V i V_i Vi与 V j V_j Vj都存在 i i i 到 j j j以及 j j j到 i i i的路径,则称其为强连通图,对应有强连通分量的概念。
好,在恶补一些基础知识后就正式进如今天的主题了:
图的读入
首先引入一堆东西,:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int vertex = 10;//点的数量
从上面的基础知识可知完全有向图的边的数量为 n ( n − 1 ) / 2 n(n − 1) / 2 n(n−1)/2而完全无向图的边的数量就为 n ( n − 1 ) n(n − 1) n(n−1)
const int edge=vertex*(vertex-1);//边的数量
int v[vertex];//点集合
在上面恶补过的基础知识后,总所周知,一条边(edge)是由一个起点,一个终点和一个权值组成,那么我们就定义一个含有一个起点,一个终点,一个权值的结构体,并定义一个边的数组:
struct edges{//定义一个关于边的结构体
int from;//本条边的左端点
int to;//本条边的右端点
double w;//本条边的权值
};
edges e[edge+1];//定义一个边的数组
然后再定义一个添加边的函数:
int cnt=1;//定义当前是第几条边
void add(int u, int v,double w){
e[cnt].from=u;//添加第cnt条边的左端点
e[cnt].to=v;//添加第cnt条边的右端点
e[cnt].w=w;//添加第cnt条边的权值
cnt++;//换下一条边
}
最后定义主函数:
int main(){
for(int i=0;i<5;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);//单向
//add(v,u,w);//双向
}
for(int i=0;i<5;i++){
printf("e[%d].from=%d\ne[%d].to=%d\n",i,e[i].from,i,e[i].to);//输出
}
}
如果是无向图的话,把代码中//add(v,u,w);//双向
这一行的注释去掉就行了。
最后附上完整代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int vertex = 10;//点的数量
const int edge=vertex*(vertex-1);//边的数量
int v[vertex];//点集合
struct edges{//定义一个关于边的结构体
int from;//本条边的左端点
int to;//本条边的右端点
double w;//本条边的权值
};
edges e[edge+1];//定义一个边的数组
int cnt=1;//定义当前是第几条边
void add(int u, int v,double w){
e[cnt].from=u;//添加第cnt条边的左端点
e[cnt].to=v;//添加第cnt条边的右端点
e[cnt].w=w;//添加第cnt条边的权值
cnt++;//换下一条边
}
int main(){
for(int i=0;i<5;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);//单向
add(v,u,w);//双向
}
for(int i=0;i<5;i++){
printf("e[%d].from=%d\ne[%d].to=%d\n",i,e[i].from,i,e[i].to);//输出
}
}