图论练习
无向图:两个有边连接的点是互通的
有向图:两个有边连接的点是不互通的,只会有一个点单向指一条边到另一个点
度:与一个节点有相连的边数量
入度:一个节点有多少条指向自己的边
出度:一个节点有多少条指向其他节点的边
最小生成树:n个结点最少需要n-1条边相连把所有点构成一个图
4408: 图的遍历
描述
图的遍历操作是从图的某一顶点出发,依次访问图中其余顶点,且每个顶点仅被访问一次。请完成无向连通图的深度优先搜索和广度优先搜索。
输入
输入数据为多组,每组数据包含多行,第一行为2个整数n(1<=n<=30),e,n为图的顶点数,e为边数,接下来是e行,每行2个整数,是一个顶点对,代表一条边所依附的两个顶点。例如,下图的输入数据为:
5 6
1 2
1 3
2 4
3 4
2 5
4 5
输出
每个图的深度优先搜索和广度优先搜索序列,每个序列占一行,输出的每个顶点后有一个空格。
样例输入
3 3
1 2
1 3
2 3
5 6
1 2
1 3
2 4
3 4
2 5
4 5
样例输出
1 2 3
1 2 3
1 2 4 3 5
1 2 3 4 5
提示
如题目描述中图所示,顶点值为整型,亦可看为顶点序号,取值从1开始。图中顶点数不超过30个,遍历时由顶点值最小的顶点开始。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 101; 4 int g[N][N],vis[N]; //创建二维数组地图g g[i][j]=0证明i和j不连通,=1证明i和j连通 5 int n,e,x,y; //n个点,e条边,x,y是连通的结点 6 void dfs(int x) 7 { 8 cout<<x<<" ";vis[x] = 1; //先输出x,并标记 9 for(int i=1;i<=n;i++) //遍历和x相连通的点,继续搜索 10 { 11 if(g[x][i]==1 && vis[i]==0) //如果x和i连通,并且i没有标记过 12 { 13 dfs(i); //以i为起点继续搜索 14 } 15 } 16 } 17 void bfs() 18 { 19 queue<int>q; 20 q.push(1);vis[1] = 1; //将起点1入队,并标记 21 while(!q.empty()) //当队列不为空时 22 { 23 int x = q.front();q.pop(); //取出队首 24 cout<<x<<" "; 25 for(int i=1;i<=n;i++) 26 { 27 if(g[x][i]==1 && vis[i]==0) //x和i连通并且i没有标记过 28 { 29 vis[i] = 1; //标记i,并让i入队 30 q.push(i); 31 } 32 } 33 } 34 } 35 int main() 36 { 37 while(cin>>n>>e) 38 { 39 memset(g,0,sizeof(g)); //清空地图,全部不相连 40 memset(vis,0,sizeof(vis)); //清空vis数组 41 for(int i=1;i<=e;i++) //构图,将e条边相连 42 { 43 cin>>x>>y; 44 g[x][y] = g[y][x] = 1;//让x和y互通 45 } 46 dfs(1); 47 cout<<endl; 48 memset(vis,0,sizeof(vis)); 49 bfs(); 50 cout<<endl; 51 } 52 return 0; 53 }
5664: 数据结构:有向图的出度和入度
描述
给定一个用邻接矩阵表示的有向图结构,问某个顶点的出度和入度。
输入
输入数据的第一行为n和m(n,m<=20),表示有n个顶点,接下来有n行,每行n个整数由0或1组成的有向图的邻接矩阵a,a[i][j]为0表示顶点i和j之间不连通,1表示连通(1<=i, j <=n)。
接下来一行有m个整数,每个整数是顶点的编号xi(从1~n编号)。
输出
输出有m行,每行输出指定顶点xi的出度和入度,用空格隔开。
样例输入
3 3
0 1 1
0 0 1
1 1 0
1 2 3
样例输出
2 1
1 2
2 2
1 #include<bits/stdc++.h> 2 using namespace std; 3 int cd[101],rd[101]; //出度cd,入度rd 4 int n ,m; 5 int main() 6 { 7 cin>>n>>m; 8 for(int i=1;i<=n;i++) 9 for(int j=1;j<=n;j++) 10 { 11 int x;cin>>x; 12 if(x) //如果x为真,那么说明i到j有一条有向边 13 { 14 cd[i]++; // i的出度++ 15 rd[j]++;// j的入度++ 16 } 17 } 18 for(int i=1;i<=m;i++) 19 { 20 int x;cin>>x; 21 cout<<cd[x]<<" "<<rd[x]<<endl; 22 } 23 return 0; 24 }
5665: 数据结构:无向图的邻接矩阵
描述
给定一个n个顶点(1到n编号)的无向图,以及若干条边,请对其构造邻接矩阵。
输入
输入数据有多组。
每组数据的第一行为两个正整数n和m,n表示顶点数(顶点从1到n编号),m表示边数。
接下来有m行,每行两个有正整数a和b (a和b不相等,1<=a,b<=n),表示顶点a到b有一条边。
但这些边可能有重复,只能算一次。
2<=n<=20, 0<=m<=n*(n-1)。
当m=n=0时,输入结束。
输出
每组输出n行n列,表示一个邻接矩阵。如果两条边有连接用1表示,否则用0表示。
样例输入
3 2
1 2
2 3
0 0
样例输出
0 1 0
1 0 1
0 1 0
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[101][101]; 4 int x,y,n,m; 5 int main() 6 { 7 while(cin>>n>>m) 8 { 9 memset(a,0,sizeof(a));//初始化地图全部为0 10 if(!n&&!m)break; 11 for(int i=1;i<=m;i++) 12 { 13 cin>>x>>y; 14 a[x][y] = a[y][x] = 1; //无向边,所以两边都要置1 15 } 16 for(int i=1;i<=n;i++) 17 for(int j=1;j<=n;j++) 18 { 19 cout<<a[i][j]; 20 if(j!=n)cout<<" "; 21 else cout<<endl; 22 } 23 } 24 25 return 0; 26 }
4670: 数据结构―有向图的最大入度和出度
描述
给定一个有向图,求顶点的最大入度和最大出度。
输入
输入数据有多组。
每组数据的第一行为两个正整数n和m,n表示顶点数(顶点从1到n编号),m表示边数。
接下来有m行,每行两个有正整数a和b (a和b不相等,1<=a,b<=n),表示顶点a到b有一条有向边。
2<=n<=20, 0<=m<=n*(n-1)。
当m=n=0时,输入结束。
输出
每组输出两个整数,即最大入度和最大出度。
样例输入
3 2
1 2
2 3
0 0
样例输出
1 #include<bits/stdc++.h> 2 using namespace std; 3 int rd[101],cd[101]; 4 int n,m,x,y; 5 int main() 6 {//4670 7 while(cin>>n>>m) 8 { 9 if(!n && !m)break; 10 memset(rd,0,sizeof(rd)); 11 memset(cd,0,sizeof(cd)); 12 for(int i=1;i<=m;i++) 13 { 14 cin>>x>>y; 15 cd[x]++; 16 rd[y]++; 17 } 18 int maxcd = -1,maxrd = -1;//最大出度maxcd,最大入度maxrd 19 for(int i=1;i<=n;i++) 20 { 21 maxcd = max(maxcd,cd[i]); 22 maxrd = max(maxrd,rd[i]); 23 } 24 cout<<maxrd<<" "<<maxcd<<endl; 25 } 26 return 0; 27 }
3649: 欧拉回路
描述
欧拉回路是指不令笔离开纸面,可画过一个连通图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
输入
测试输入包含若干测试用例。
每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M。
随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。
当N为0时输入结束。
输出
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
样例输入
3 3
1 2
1 3
2 3
3 2
1 2
2 3
0
样例输出
1
0
1 #include<bits/stdc++.h> 2 using namespace std; 3 int f[1001],d[1001]; 4 int n,m; 5 int find(int x) 6 { 7 if(f[x]!=x)f[x] = find(f[x]); 8 return f[x]; 9 } 10 void merger(int x,int y) 11 { 12 int fx = find(x); 13 int fy = find(y); 14 f[fy] = fx; 15 } 16 int main() 17 { 18 while(cin>>n,n) 19 { 20 cin>>m; 21 for(int i=1;i<=n;i++)f[i] = i; 22 memset(d,0,sizeof(d)); 23 for(int i=1;i<=m;i++) 24 { 25 int x,y;cin>>x>>y; 26 d[x]++;d[y]++; 27 if(find(x)!=find(y)) 28 { 29 merger(x,y); 30 } 31 } 32 int sum = 0,k = 1; 33 for(int i=1;i<=n;i++) 34 { 35 if(f[i]==i)sum++; //寻找父节点个数 36 if(d[i]%2!=0)k = 0; //判断第i个结点的度是否不为偶数 37 } 38 if(sum==1&&k)cout<<1<<endl; //如果整个图只有1个父节点,并且每个点的度都是偶数,那么就是欧拉回路 39 else cout<<0<<endl; 40 } 41 return 0; 42 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现