图论基础

基础概念

https://oi-wiki.org/graph/concept/

  • DAG : 有向无环图
  • 如果一张无向连通图包含恰好一个环,则称它是一棵 基环树 (pseudotree),其具有n个顶点n条边
  • 在无向图中,关联一对顶点的无向边如果多于1条,则称这些边为平行边,平行边的条数称为重数。在有向图中,关联一对顶点的有向边如果多于1条,并且这些边的始点与终点相同(也就是他们的方向相同),称这些边为平行边。含平行边的图称为多重图,既不含平行边也不含环的图称为简单图。

路径

路径 (path)(又称 简单路径 (simple path)):路径上顶点和边均不相同

连通

  • 无向图

无向图中,如果任意两个顶点之间都能够连通,则称此无向图为连通图
定义连通子图为连通分量

  • 有向图

若一张有向图的节点两两互相可达,则称这张图是 强连通的 (strongly connected)
若一张有向图的边替换为无向边后可以得到一张连通图,则称原来这张有向图是 弱连通的 (weakly connected)

类似定义强连通分量弱连通分量

存图方法

邻接矩阵

G[N][N]

邻接表

vector<int> e[maxm]

链式前向星

这个方法很有意思,充分地利用了指针的性质,实现了分散存储两个顶点的连接关系,颇有种链表的感觉。

  • 链式前向星存无向图记得二倍边长空间!!!
  • 初始cnt=1,head 数组默认初始全0,这样后面循环的时候判断 i 是否不为 0 即可

利用链式前向星存无向图

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define ull unsigned long long
//#define int long long

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}

using namespace std;
const int maxm=2e5+5;
int n,head[maxm],cnt;
struct edge1{
	int to,next;
}p[maxm];

void add_edge1(int a,int b){//无向无边权 
	p[cnt].to=b;			//cnt起点,b终点 
	p[cnt].next=head[a];	//标记前面一个同起点点的位置 
	head[a]=cnt++;			//更新下标 
	return ;
}

void solve(){
	cin>>n;
	memset(head,-1,sizeof(head));//利用-1来标记是否遍历到了根节点 
	int a,b;
	cnt=0;
	for(int i=0;i<n;++i){
		cin>>a>>b;
		add_edge1(a,b);
		add_edge1(b,a);
	}
	for(int i=1;i<=n;++i){
		cout<<i<<"..."<<head[i]<<endl;
		for(int j=head[i];j>=0;j=p[j].next){//遍历的方法 
			cout<<p[j].to<<'#';
		}
		cout<<endl;
	}
	return ;
}

signed main(){
//	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int cs=1;
//	cin>>cs;
	while(cs--){
		solve();
	}
	return 0;
}
posted on 2023-02-28 23:01  Qiansui  阅读(25)  评论(0编辑  收藏  举报