图论基础学习指南
图的存储方式
邻接矩阵
w[u][v]存储从点u到点v的边的权值。
时间复杂度:
空间复杂度:
应用:只在点数不多的稠密图,(n=103,m=106)上使用。
const int N=1010;
int g[N][N];
int vis[N];
int n,m;
int u,v,w;
void dfs(int u){
vis[u]=true;
for(int v=1;v<=n;v++){
if(g[u][v]){
// pass;
if(vis[v]) continue;
dfs(v);
}
}
}
int main() {
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
w[u][v]=w;
// w[v][u]=w;
}
dfs(1);
return 0;
}
边集数组
边集数组e[i]存储第i条边的{起点u,终点v,边权w}
时间复杂度:
空间复杂度:
应用:在Kruskal算法中,需要将边按边权排序的,直接存边。
const int N=1010,M=1010;
int n,m,a,b,c;
struct edge{
int u,v,w;
}e[M];//边集
int vis[N];
void dfs(int u){
vis[u]=true;
for(int i=1;i<=m;i++)
if(e[i].u==u){
int v=e[i].v,w=e[i].w;
printf("%d,%d,%d\n",u,v,w);
if(vis[v]) continue;
dfs(e[i].v);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a>>b>>c;
e[i]={a,b,c};
// e[i]={b,a,c};
}
dfs(1);
return 0;
}
邻接表
出边数组e[u][i]存储u点的所有出边d{终点v,边权w}
时间复杂度:
空间复杂度:
应用:各种图,不能处理反向边。
const int N=510;
int n,m,a,b,c;
struct edge{int v,w;};
vector<edge> e[N];//边集
void dfs(int u,int fa){
for(auto ed : e[u]){
int v=ed.v, w=ed.w;
if(v==fa) continue;
printf("%d,%d,%d\n",u,v,w);
dfs(v, u);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a>>b>>c,
e[a].push_back({b,c});
// e[b].push_back({a,c});
}
dfs(1, 0);
return 0;
}
链式邻接表
const int N=510;
int n,m,a,b,c;
struct edge{int u,v,w;};
vector<edge> e;//边集
vector<int> h[N];//点的所有出边
void add(int a,int b,int c){
e.push_back({a,b,c});
h[a].push_back(e.size()-1);
}
void dfs(int u,int fa){
for(int i=0;i<h[u].size();i++){
int j=h[u][i];
int v=e[j].v,w=e[j].w;
if(v==fa) continue;
printf("%d,%d,%d\n",u,v,w);
dfs(v,u);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a>>b>>c,
add(a,b,c);
add(b,a,c);
}
dfs(1, 0);
return 0;
}
链式前向星
这两条边可以通过互为反向边,可以通过与1的异或运算得到其反向边,01=1,11=0。也就是说如果一条边的下标为i,则其反向边为i^1(需要从0编号开始建图)。这个特性应用在网络流中非常方便。
链式前向星的空间复杂度是O(n)
【结构体写法】
const int N=510,M=3000;
int n,m,a,b,c;
struct edge{int v,w,ne;};
edge e[M];//边集
int idx,h[N];//点的第一条出边
void add(int a,int b,int c){
e[idx]={b,c,h[a]};
h[a]=idx++;
}
void dfs(int u,int fa){
for(int i=h[u];~i;i=e[i].ne){
int v=e[i].v, w=e[i].w;
if(v==fa) continue;
printf("%d,%d,%d\n",u,v,w);
dfs(v,u);
}
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++){
cin>>a>>b>>c,
add(a,b,c);
add(b,a,c);
}
dfs(1, 0);
return 0;
}
【数组写法】
const int N=2e5+10;
int h[N],e[N],ne[N],idx=0;
void add(int u,int v){
e[++idx]=v;
ne[idx]=h[u];
h[u]=idx;
}
void dfs(int x,int fa){
for(int i=h[x];i;i=ne[x]){
if(e[i]!=fa) dfs(e[i],x);
}
}