感觉图论嗑得差不多了做点总结吧。
听所图论题套模板,下面就给一些模板吧。
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。