存图方式

存图方式

在进行图上的一些操作时,存图,是必要的前置操作。

e.g.

接下来的 Code 以这为测试:

# input
4 5
1 2
1 3
2 4
1 4
3 4

朴素做法

邻接矩阵,便是一种简单的结构,使用 bool 类型为底,如果 \(u \to v\) 有边,\(a_{u,v} = 1\),否则 \(a_{u,v} = 0\)

Code1

#include <iostream>
using namespace std;
bool a[105][105];
void addedge(int u,int v)
{
	a[u][v]=true;
	return ;
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int u,v;
		cin>>u>>v;
		addedge(u,v);
		addedge(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++) cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}
# output
0 1 1 1
1 0 0 1
1 0 0 1
1 1 1 0

升级做法

可想而知,这样的空间复杂度是非常高昂的,因此,我们使用 vector 来优化,如果 \(u \to v\) 有边,则有 \(vec_{u,i} = v\),否则没有 \(vec_{u,i} = v\)

Code2

#include <iostream>
#include <vector>
using namespace std;
vector<int> vec[105]; 
void addedge(int u,int v)
{
	vec[u].push_back(v);
	return ;
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int u,v;
		cin>>u>>v;
		addedge(u,v);
		addedge(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		cout<<i<<": ";
		for(int j=0;j<vec[i].size();j++) cout<<vec[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}
# output
1: 2 3 4
2: 1 4
3: 1 4
4: 2 1 3

再升级做法

即一种基于数组模拟链表的策略。

  • \(h\) 数组是 head 表示第一项;
  • \(to\) 是可以到达的点;
  • \(nxt\) 是这一项下一项的地址。

Code3

#include <iostream>
using namespace std;
int h[105],tot;
struct CFS
{
	int to;
	int nxt;
	CFS(){};
	CFS(int t,int n){
		nxt=n;
		to=t;
	};
}edge[10005];
void addedge(int u,int v)
{
	tot++;
	edge[tot]=CFS(v,h[u]);
	h[u]=tot;
	return ;
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int u,v;
		cin>>u>>v;
		addedge(u,v);
		addedge(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		cout<<i<<": ";
		for(int j=h[i];j;j=edge[j].nxt) cout<<edge[j].to<<" ";
		cout<<endl;
	}
	return 0;
}
# output
1: 4 3 2
2: 4 1
3: 4 1
4: 3 1 2
posted @ 2024-07-09 20:07  RainCQwQ  阅读(23)  评论(0)    收藏  举报