图描述的是一些个体之间的关系。这些个体之间既不是前驱后继的顺序关系,也不是祖先后代的层次关系,而是错综复杂的网状关系。我们一般用图 G = ( V , E ) G=(V,E) G=(V,E)来表示, V V V表示结点, E E E表示边。
根据边是否有权值,分为带权图和不带权图,也可将不带权图视为权重都为 1 1 1的图。
根据边是否有方向,分为有向图和无向图。
根据稠密程度(边的条数 ∣ E ∣ |E| ∣E∣与 ∣ V ∣ 2 |V|^2 ∣V∣2)的关系,分为稠密图和稀疏图。
树是一种特殊的图,它满足 ∣ V ∣ = ∣ E ∣ + 1 |V|=|E|+1 ∣V∣=∣E∣+1。将其中一个结点作为根节点,表示所有结点的祖先。
对于树上的连边,靠近根节点的结点被叫做父结点,远离根节点的结点被叫做子节点。一个结点只有一个父节点,但可以有多个子节点。具有相同父节点的结点互称为兄弟结点。
对于无向图来说,一个结点的度等于该结点所连的边数。
对于有向图来说,一个结点的入度等于连向该结点的边数,一个结点的出度等于连出该结点的边数。
对于图 G = ( V , E ) G=(V,E) G=(V,E)和图 G ′ = ( V ′ , E ′ ) G'=(V',E') G′=(V′,E′)来说,如果满足 V ′ ∈ V , E ′ ∈ E V'\in V,E'\in E V′∈V,E′∈E,则 G ′ G' G′是 G G G的子图。
对于无向图 G = ( V , E ) G=(V,E) G=(V,E)来说:
对于有向图 G = ( V , E ) G=(V,E) G=(V,E)来说:
邻接矩阵即使用一个二维数组来完全表示一个图。
m p [ u ] [ v ] = w mp[u][v]=w mp[u][v]=w表示存在一条从结点 u u u到结点 v v v的权重为 w w w的边。
对于无向边,可以视为两条方向相反、连接结点相同的边。
const ll maxn=1010;
ll n,m,mp[maxn][maxn];
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
mp[u][v]=w;
//mp[v][u]=w;
}
return 0;
}
邻接表在表示稀疏图时非常紧凑,节省空间,所以成为通常用来表示图的方法。
数组 p [ u ] p[u] p[u]表示结点 u u u的最后一条边, p [ u ] = = − 1 p[u]==-1 p[u]==−1则表示点 u u u没有别的边了。 t t t表示边的数量。
数组 e [ t ] e[t] e[t]表示第 t t t条边的所有信息,其中 v v v表示边的终点, w w w表示边的权重, n e x t next next表示具有同样起点的另一条边。
const ll maxn=100010;
struct node
{
ll v;
ll w;
ll next;
}e[maxn*2];
ll n,m,p[maxn],t=0;
void insert(ll u,ll v,ll w)
{
e[t].v=v;
e[t].w=w;
e[t].next=p[u];
p[u]=t++;
}
int main()
{
memset(p,-1,sizeof(p));
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
insert(u,v,w);
//insert(v,u,w);
}
return 0;
}
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1010;
ll n,m,mp[maxn][maxn];
void dfs(ll u,ll pre)
{
cout<<"u="<<u<<endl;
for(ll i=1;i<=n;i++)
{
if(i!=pre)
dfs(i,u);
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
mp[u][v]=w;
mp[v][u]=w;
}
return 0;
}
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=100010;
struct node
{
ll v;
ll w;
ll next;
}e[maxn*2];
ll n,m,p[maxn],t=0;
void insert(ll u,ll v,ll w)
{
e[t].v=v;
e[t].w=w;
e[t].next=p[u];
p[u]=t++;
}
void dfs(ll u,ll pre)
{
cout<<"u="<<u<<endl;
for(ll i=p[u];i!=-1;i++)
{
ll v=e[i].v;
if(v!=pre)
dfs(v,u);
}
}
int main()
{
memset(p,-1,sizeof(p));
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
insert(u,v,w);
insert(v,u,w);
}
return 0;
}