【图论】图,实现图(三种方式),二分图 详解
目录
- 一.图的基本概念
- 1.度
- 2.连通
- (1)连通图
- (2)强连通/强连通图
- 3.回路
- 4.完全图
- 二. 邻接矩阵实现图
- 三.邻接表实现图
- 四.链式前向星实现图
- 五. 二分图
- 概述
- 1.简单应用—二分图的判定
- 2.P1155 双栈排序(二分图的染色判断+链式前向星)
一.图的基本概念
图(graph)并不是指图形图像(image)或地图(map)。通常来说,我们会把图视为一种由“顶点”组成的抽象网络,网络中的各顶点可以通过“边”实现彼此的连接,表示两顶点有关联。注意上面图定义中的两个关键字,由此得到我们最基础最基本的2个概念,顶点(vertex)和边(edge)。
如上图所示,节点(vertex)用红色标出,通过黑色的边(edge)连接。
1.度
与结点关联的边数,在有向图中为入度与出度之和。
出度:在有向图中以这个结点为起点的有向边的数目。(可形象的理解为离开这个结点的边的数目)
入度:在有向图中以这个结点为终点的有向边的数目。(可形象的理解为进入/指向这个结点的边的数目)
任意一个图的总度数等于其边数的2倍
2.连通
如果在同一无向图中两个结点存在一条路径相连,则称这两个结点连通。
(1)连通图
如果无向图中任意两个结点都是连通的,则称之为连通图。
(2)强连通/强连通图
如果有向图中任意两个结点之间存在两条路径(即(i,j)两点中,既从i到j有一条路径,j到i也有一条路径),则两点是强连通的。当一个图中任意两点间都是强连通的,则该图称之为强连通图。
在强连通图中,必定有一条回路经过所有顶点。
强连通分量:非强连通图有向图中的最大子强连通图。
3.回路
起点与相同的路径,又叫“环”。
4.完全图
任意两点间都存在边使其相连的无向图或任意两点间都存在两条不同边的有向图称作完全图
N个顶点的完全图:
有向 有n(n-1)条边
无向 有n(n-1)/2条边
上述内容参考
二. 邻接矩阵实现图
邻接矩阵使用二维数组或vector
来表示图,g[i][j]
表示顶点i
和顶点j
的关系
无向图:
需要使
g[i][j]=g[j][i]
g[i][j]
表示顶点i
和顶点j
的边数(0/1/2...
)(对于重边或自环)
有向图:
不需要
g[i][j]=g[j][i]
一般有权有向图,权值可能为0,所以如果两点之间无边就使
g[i][j]=INF
若有重边可以根据题意只保存权值最大或最小的边即可
邻接矩阵实现图的优点:
- 可以O(1)O(1)O(1)查询两点之间是否有边
缺点:
- 内存占用过大,O(V2)O(V^2)O(V2)的空间,对于树这种图而言太过于浪费
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<"# "<<x<<" "<<endl;
typedef long long ll;
const ll mod=2147483647;
const ll N=1e4+7;
struct vertex
{vector<vertex*>edge;/*******顶点的属性*/
};
vertex G[N];
int main()
{ll V,E;scanf("%lld %lld",&V,&E);for(int i=0;i<E;++i){ll s,t;scanf("%lld %lld",&s,&t);G[s].edge.push_back(&G[t]);//有向图不需要,无向图需要//G[t].edge.push_back(&G[s]);}/******各种图的操作*/return 0;
}
———————————————————————————————————
vertex* ShortestPath(vertex G[],int query_id,int d)
在这个函数里,作为返回值的G0一切正常,可是在调用ShortestPath函数将其值存入vertex *G0中后,G0中的值全部丢失了。
不要返回局部对象的引用或指针,因为函数完成后,它所占的存储空间也随之释放掉。 因此,函数终止意味着局部变量的引用将指向不再有效的内存区域。此bug来源
———————————————————————————————————
三.邻接表实现图
优点:
- 内存占用较小只需要O(∣V∣+∣E∣)O(|V|+|E|)O(∣V∣+∣E∣)的内存
缺点:
- 实现带权图较为复杂
- 查询两点是否有边需要遍历一遍链表,每次都是O(V)O(V)O(V)的时间
输入:
3 3
0 1//有一条0到1的边
0 2
1 2
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<"# "<<x<<" "<<endl;
typedef long long ll;
const ll mod=2147483647;
const ll N=1e4+7;
vector<ll>G[N];//graph
/*
如果边上有属性(带权图)
struct edge
{ll to,cost;
};
vector<edge>G[N];
*/
int main()
{ll V,E;//V个顶点和E条边scanf("%lld %lld",&V,&E);for(int i=0;i<E;++i){ll s,t;//从s到tscanf("%lld %lld",&s,&t);G[s].push_back(t);}/***********各种对图的操作*/return 0;
}
四.链式前向星实现图
【链式前向星+存图】讲解
链式前向星:
若果有五个点,假设把他们想做是一个个的小房间,每个房间中藏有其他房间的钥匙,每个房间可以通往其他人的房间。现在我来讲一讲他的具体步骤吧:
有一个东西叫做st的里面存储的是第i条路的路径数。 所以呢,我们可以定一个结构体,具体代码如下:
struct node
{ll v,nex,val,u;
}e[N];ll head[N],cnt;inline void add(ll u,ll v,ll val)//从u到v,从父节点到子节点
{e[++cnt].nex=head[u];e[cnt].val=val;//可有可无e[cnt].v=v;e[cnt].u=u;//可有可无head[u]=cnt;
}
注意遍历时候的循环跟普通的方法不一样!
for(ll i=head[u];i;i=e[i].nex){ll v=e[i].v;---------------}//这样我们就可以遍历全部的点了!!!:)
建议直接把上面的几行代码背下来,具体到底是什么意思懂不懂无所谓,会用就行。
五. 二分图
概述
二分图又称作二部图,是图论中的一种特殊模型。设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
如上图就是一个标准的二分图
1.简单应用—二分图的判定
此题来源于《挑战程序设计竞赛》
DFS
vector<int> G[MAX_V];//图的表示
int V;//顶点数
int color[MAX_V];//顶点i的颜色1或-1
//把顶点染成1或-1
bool dfs(int v,int c)
{color[v]=c;//顶点v染成cfor (int i = 0; i < G[v].size(); ++i){//相邻点同色,返回falseif(color[G[v][i]]==c)return false;//相邻点没有染色,就将其染色为-c,继续dfs,若最终仍为false,则返回falseif(color[G[v][i]]==0 && !dfs(G[v][i],-c))return false;}//所有顶点染过色返回truereturn true;
}
void solve()
{//如果是连通图,则一次dfs即可访问所有位置//但题目没有说明,故要依次检查各个顶点的情况for (int i = 0; i < V; ++i){if (color[i]==0){//如果顶点还没有染色,染成1if (!dfs(i,1)){cout<<"No"<<endl;return;}}}cout<<"Yes"<<endl;
}
以及BFS
int n,m;
vector<int> g[MAXN];
int color[MAXN];
void init()
{for(int i=0;i<n;i++){g[i].clear();color[i]=-1;}
}
int bfs()
{queue<int>q;q.push(0);color[0]=1;while(!q.empty()){int t = q.front();q.pop();for(int i=0;i<g[t].size();i++){if(color[g[t][i]]==color[t])//相邻节点颜色相同,不是二分图return 1;else if(color[g[t][i]]==-1)//未染色{color[g[t][i]]=-color[t];q.push(g[t][i]);}}}return 0;
}
#include<bits/stdc++.h>
#define MAX_V 210
using namespace std;
vector<int>G[MAX_V];//这里用不定长数组,来存图。
int V,E,color[MAX_V];
bool dfs(int v,int c)
{color[v] = c;for(int i=0;i<G[v].size();i++){//连接这个节点的所有节点 if(color[G[v][i]] == c) return false;if(color[G[v][i]] == 0 && !dfs(G[v][i],-c)) return false;/*注意这一步,不能分解,因为当该层的下一层,返回false时,到递归回到这一层仍要返回false。*/ }return true;
}
void solve()
{if(!dfs(0,1)){//本题是从0这个节点来搜索就可,但有些题目,图可能不是联通的,故要从头到尾遍历一遍。 printf("NOT BICOLORABLE.\n");return;}printf("BICOLORABLE.\n");return;
}
int main(void)
{while(~scanf("%d",&V)){scanf("%d",&E);memset(color,0,sizeof(color));memset(G,0,sizeof(G));int a,b;for(int i=0;i<E;i++){scanf("%d %d",&a,&b);//注意是无向图G[a].push_back(b);G[b].push_back(a);}solve();}return 0;
}
2.P1155 双栈排序(二分图的染色判断+链式前向星)
P1155 双栈排序
P1155 双栈排序(二分图的染色判断+链式前向星)
注:如果您通过本文,有(qi)用(guai)的知识增加了,请您点个赞再离开,如果不嫌弃的话,点个关注再走吧 ! 当然,也欢迎在讨论区指出此文的不足处,作者会及时对文章加以修正 !
【图论】图,实现图(三种方式),二分图 详解相关推荐
- 详解python运行三种方式_详解python运行三种方式
方式一 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码. linux上你只需要在命令行中输入 Python 命令即可启动交互式编程,提示窗口如下: $ p ...
- java实现线程三种方式_详解三种java实现多线程的方式
java中实现多线程的方法有两种:继承Thread类和实现runnable接口. 1.继承Thread类,重写父类run()方法 public class thread1 extends Thread ...
- VMware Workstation网络连接的三种方式原理详解 与 配置过程图解
VMware workstations为我们提供了三种网络工作模式,它们分别是:Bridged(桥接模式).NAT(网络地址转换模式).Host-Only(仅主机模式). 打开vmware虚拟机,我们 ...
- 详解python运行三种方式_详解python调用cmd命令三种方法
目前我使用到的python中执行cmd的方式有三种 使用os.system("cmd") 该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码, ...
- Spring详解-------依赖注入的三种方式实例详解
目录 1.什么是依赖注入 1.1类的关系 1.1.1 依赖关系(Dependency) 1.1.2 聚合(Aggregation) 1.2关系强度 2 为什么使用依赖注入 2.1开闭原则 2.1.1 ...
- 测绘用计算机吗,三种测量仪器使用详解,测绘人必须要知道
原标题:三种测量仪器使用详解,测绘人必须要知道 水准仪及其使用方法 高程测量是测绘地形图的基本工作之一,另外大量的工程.建筑施工也必须量测地面高程,利用水准仪进行水准测量是精密测量高程的主要方法,具体 ...
- VM虚拟机三种网络模式详解
感谢wuwenweijuan的优质文章,本文在该文基础上做了注和补充 目录 1 VM虚拟机三种网络模式详解 1.1 Bridged(桥接模式) 1.2 NAT(地址转换模式) 1.3 Host-Onl ...
- 虚拟机的三种网络模式详解
虚拟机的三种网络模式详解 1. 桥接模式: 此模式下,虚拟机的操作系统就像和物理机同一段网络中的物理机一样,它可以访问网络中的任何机器,同时只要物理机可以访问网络,虚拟机也可以实现上网.此模式是懒人模 ...
- 9. PKI - 三种密钥交换算法详解(RSA DHE ECDHE)及他们在SSL/TLS协议中的应用
9. PKI - 三种密钥交换算法详解(RSA& DHE& ECDHE)及他们在SSL/TLS协议中的应用 RSA密钥交换算法 DHE密钥交换算法 ECDHE密钥交换算法 参考 密钥交 ...
- java的websocket_java 实现websocket的两种方式实例详解
一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...
最新文章
- react native报错:Expected a component class,got[object object]
- PS 技术篇-使用ps快速完成证件照片换背景色实例演示10s搞定!
- anaconda3配置环境变量_阿里云ECS配置Jupyter Notebook
- 2021热度不减的在线教育,正在努力成为线下教育的有益补充
- 游戏音乐是游戏内涵的补充
- ajax 传参数 java后台接收
- 查看某个端口的进程 lsof -i:端口号
- linux下gdb单步调试
- mac下终端命令行下添加mysql命令
- 《SaaS架构设计》试读:前 言
- vue 中引入使用jquery
- Elasticsearch集群安全防护提出几个建议
- java mov 转 mp4 视频格式
- DNS 智能解析功能评测之华为云篇~
- SDRAM中的DQM
- java 单位圆_巧用蒙特卡洛算法求单位圆面积
- C语言学习一些指针随笔记
- 纽约州立大学石溪分校肖可瓅:数据驱动的金融研究
- linux、linux虚拟机相关
- Android 高级混淆和代码保护技术
热门文章
- 只用一张训练图像进行图像的恢复
- 用于目标检测的半自动视频标注
- Ret2Libc(2) (有system、无‘/bin/sh’)绕过NX、ASLR
- 其实win10要比win7的安全性强很多
- Spring之定时任务基本使用篇
- Hadoop概念学习系列之Java调用Shell命令和脚本,致力于hadoop/spark集群(三十六)...
- Java基础--定时任务Timer
- MaxScale:实现MySQL读写分离与负载均衡的中间件利器
- Android4.2以后,多屏幕的支持 学习(一)
- ExtJs grid合并单元格