图的存储结构
#define maxnn 10000
using namespace std;
typedef struct {
int no;//顶点编号
//infotype info; 顶点的其他信息
}vertextype;//顶点类型
typedef struct {
int edge[maxnn][maxnn];//邻接矩阵数组 发现如果maxnn定义过大的话会报错
int n, e;//顶点和边数
vertextype vexs[maxnn];//存放顶点信息
}matgraph;//完整的图邻接矩阵类型
//图的邻接矩阵的表示是唯一的,无论有向图还是无向图,无论边的数目,存储空间都是o(n的平方) 无向图的邻接矩阵一定是对称矩阵 反之未必
//在用邻接表来表示图时,图中的每个顶点v都对应一个单链表,每个单链表有一个头结点 所有这些头结点构成头结点数组
typedef struct anode {
int adjvex;//该边的邻接点编号
struct anode* nexarc;//指向下一条边的指针
int weight;//该边的相关信息,比如权值
}arcnode;//边结点类型
typedef struct vnode {
//InfoTyoe info; 顶点的其他信息
arcnode* firstarc;//指向第一个边结点
}Vnode;//邻接表头结点类型
typedef struct {
vnode adjlist[10000];//邻接表头结点数组
int n, e;//图中顶点数n和边数e
}adjgraph;//完整的图邻接表类型
//邻接表的表示不唯一,是因为在每个顶点对应的单链表中各边的连接次序可以是任意的,取决于建立邻接表的算法和输入边的次序
//对于有n个顶点和e条边的无向图,其邻接表有n个头结点和2e个边结点,对于有n个顶点和e条边的有向图,其邻接表有n个头结点和e个边结点
在有向图的邻接表表示中,顶点v的单链表中结点个数等于顶点v的出度
并查集
最简单的实现:一个root数组,即int root[maxn];若root[i] = j;则顶点j是i的前驱顶点或双亲,其中root[j]=j的顶点j为该集合的根或者代表。初始时root[i]=i;
即初始化算法如下:
void init()
{
for(int i = 0;i < maxv;i++)
root[i]=i;
}
查找顶点i的集合编号的算法:
int Find(int i)
return i==root[i]?i:Find(root[i]);
###将顶点i和j所在集合进行合并的算法:
void union(int i,int j)
{
int x = Find(i);
int y = Find(j);
if(x != y)
root[x] = y;
}
利用并查集求无向图连通分量的个数
输入若干测试用例,每个测试样例第一行包括两个整数n m,分别代表n个顶点(顶点编号为0~n-1),m条边,下面的m行 每行有两个整数u,v;表示顶点u v之间有一条边,测试以n=0结束,要求输出每个测试样例对应的连通分量的个数。
解析:用并查集,对于输入边(a,b) 通过union(a,b)将a,b的连通分量合并,输入结束后,root[i]==i的顶点个数即连通分量的个数。
#include<string>
#include<iostream>
#define max 10000;
int root[max];
int rank[max];
//并查集的基本运算算法
void init(int n)
{
for(int i = 0;i <n;i++)
{root[i]=i;
rank[i]==0;
}
}
int find(int x)
{
if(x != root[x])
root[x]=find(root[x]);
return root[x];
}
void union(int x,int y)
{
if((x=find(x))==(y=find(y))
return;
else
if(rank[x]>rank[y])
root[y]=x;
else
{
root[x]=y;
if(rank[x]==rank[y])
rank[x]++;
}
}
int main()
{
int n,m,i;
int a,b;
int sum;
while(1)//一个while对应一个测试用例
{
cin>>n>>m;
if(n == 0)break;
init(n);
for(int i = 0;i < m;i++)
{
cin>>a>>b;
union(a,b);//合并a b的连通分量
}
sum = 0;
for(int i = 0;i < n;i++)
if(find(i)==i)
sum++;//如果顶点i的根为i,对应一个连通分量
}
}
树或图的宽度(广度)优先搜索算法通常用队列实现,从根结点开始,沿着树的宽度遍历树的结点,如果所有结点均被访问则算法中止。空间复杂度为o(v+e) V是结点数量,e是边的数量,时间复杂度是o(v+e),因为必须寻找所有到可能结点的所有路径