图论总结(1)深度优先遍历

感觉图论嗑得差不多了做点总结吧。

听所图论题套模板,下面就给一些模板吧。

1.DFS框架(依次递归访问当前节点的所有相邻节点):

 

vectorG[maxn];
int vis[maxn];
void dfs(int u){
	vis[u]=1;
	PREVISIT(u);//访问u前的操作
	int d=G[u].size();
	for(int i=0;i

2.欧拉回路(一笔画问题):

 

如果一个图存在一笔画(不重复走完所有的边),则一笔画的路径叫做欧拉路,如果最后又回到了起点,那这个路径叫做欧拉回路。

我们定义奇点是指跟这个点相连的边数目有奇数个的点,给出下面两个定理。

定理1:存在欧拉路的条件:图是联通的,有且只有两个奇点。

定理2:存在欧拉回路的条件:图是联通的,没有奇点。

下面给出模板:

先遍历找到较小奇点从这个奇点开始 

 

int G[maxn][maxn],circuit[maxn],circuitpos;//用邻接矩阵保存边
void euler(int i){
	int j;
	for(j=1;j<=n;j++)if(G[i][j]){
		G[i][j]=G[j][i]=0;
		euler(j);
	}
	circuit[++circuitpos]=i;//用来记录路径
}

判断是欧拉路还是欧拉回路直接用定理,遍历一次就行。

 

不足的是上程序只能找一个回路,具体问题还需作出相应修改。

3.哈密顿环

和欧拉回路很像,只是将不重复走过所有边改为了不重复走过所有点。

直接给模板:

 

 

//ÿ¸öµã¶¼×÷ΪÆðµã³¢ÊÔ·ÃÎÊ£¬Ó¦Îª²»ÊÇ´ÓÈκÎÒ»µã¿ªÊ¼¶¼ÄÜÕÒµ½Õû¸öͼint ans[maxn],vis[maxn],vl[maxn];
vectorG[maxn][maxn];
int cnt,x;
void print(){
	int i;
	for(i=1;i<=cnt-1;i++)
	cout<

上程序可以一次性找出所有的哈密顿环。

 

4.求联通分量(无向图):

种子填充问题

求联通分量个数

模板:

 

int G[maxn][maxn],vis[maxn];
void dfs(int i,int id){
	vis[i]=id;
	for(int j=1;j<=n;j++)if(!vis[j]&&G[i][j]){
		dfs(j,id);
	}
}
void solve(int i){
	int cnt=0;//用来记录编号
	memset(vis,0,sizeof(vis));
	int ans=0;
	for(int i=1;i<=n;i++)if(!vis[maxn]){
		dfs(i,++cnt);
		ans++;
	}
}

5.二分图判定
二分图定义略

 

给出二分图的一种等价说法:可以把每个节点着以黑色和白色之一,是的每条边的两个端点颜色不同。

不难发现非连通图是二分图当且仅当每个连通分量是二分图,因此我们仅考虑无向连通图。

下面用DFS来给任意无向图G进行黑白着色。
首先假定节点1是黑色的(白色也一样)。

int color[maxn];
bool bipartite(int u){
	for(int i=0;i

我们用颜色1,2表示黑色和白色,0表示未涂色,就不需要vis数组了。记得将color数组初始化为0。
 

 

 

你可能感兴趣的:(图论总结)