图论基础
基础概念
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;
}
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17166439.html