存图方式
在进行图上的一些操作时,存图,是必要的前置操作。
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
标签:方式,int,tot,存图,vec,include,addedge,105
From: https://www.cnblogs.com/zhangyuyi1218/p/-/input_graph