当前位置:   article > 正文

洛谷题单 -- 图论的简单入门_b3643 图的存储

b3643 图的存储

B3643 图的存储

链接 : 

图的存储 - 洛谷

思路 : 

这一题要考察图的存储方式 , 一般可以使用邻接矩阵 或 邻接表来存储 图的结点 和1 边的信息 ,详情请看代码 : 

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1010 ;
  4. int n , m ;
  5. int a[N][N] ; // 邻接矩阵
  6. vector<int> b[N]; // 邻接表
  7. // 邻接矩阵的输出
  8. void pa(){
  9. for(int i=1;i<=n;i++){
  10. for(int j=1;j<=n;j++){
  11. cout << a[i][j] << " ";
  12. }
  13. cout << endl ;
  14. }
  15. }
  16. // 邻接表的输出
  17. void pb(){
  18. for(int i=1;i<=n;i++){
  19. int d = b[i].size();
  20. cout << d << " ";
  21. sort(b[i].begin(),b[i].end());
  22. for(int j=0;j<d;j++){
  23. cout << b[i][j] << " ";
  24. }
  25. cout << endl ;
  26. }
  27. }
  28. int main(){
  29. cin >> n >> m;
  30. for(int i=0;i<m;i++){
  31. int x , y ; cin >> x >> y ;
  32. a[x][y] = 1 ; a[y][x] = 1 ; // 邻接矩阵
  33. b[x].push_back(y) ; b[y].push_back(x) ; // 邻接表
  34. }
  35. pa();
  36. pb();
  37. return 0 ;
  38. }

P5318 【深基18.例3】查找文献

链接 

【深基18.例3】查找文献 - 洛谷

思路 : 

这题考察有向图的 dfs 和 bfs ,详情请看代码,如果用邻接矩阵的话一定会mle,只能够使用邻接表,我这里采用的是用vector数组实现的邻接表,详情请看代码 : 

代码 

  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <cstring>
  5. #include <algorithm>
  6. using namespace std;
  7. const int N = 1e5 + 10 ;
  8. typedef long long LL ;
  9. int n , m , x , y;
  10. bool b[N] ; // 状态记录数组
  11. vector<int> a[N] ; // 邻接表
  12. queue<int> q;
  13. inline int read(){//二进制优化的快读
  14. int x=0,f=1;
  15. char ch=getchar();
  16. while(ch<'0'||ch>'9'){
  17. if(ch=='-')
  18. f=-1;
  19. ch=getchar();
  20. }
  21. while(ch>='0'&&ch<='9'){
  22. x=(x<<1)+(x<<3)+(ch^48);
  23. ch=getchar();
  24. }
  25. return x*f;
  26. }
  27. // x指当前遍历到的结点,r表示已遍历过的结点
  28. void dfs(int x , int r){
  29. b[x] = true ;
  30. cout << x << " " ; // 输出
  31. if(r == n) return ;
  32. for(int i=0;i<a[x].size();i++){
  33. if(!b[a[x][i]])
  34. dfs(a[x][i],r+1);
  35. }
  36. }
  37. void bfs(int x){
  38. memset(b , false , sizeof(b)) ; // 清空bool数组
  39. b[x] = true ;
  40. q.push(x) ;
  41. while(!q.empty()){ // 还有没有没访问的
  42. int v = q.front();
  43. q.pop() ; // 弹出队头 , 否则会一直在第一层遍历
  44. cout << v << " " ;
  45. for(int i=0;i<a[v].size();i++){
  46. if(!b[a[v][i]]){
  47. b[a[v][i]] = true ;
  48. q.push(a[v][i]);
  49. }
  50. }
  51. }
  52. }
  53. int main(){
  54. // n = read() ; m = read() ;
  55. cin >> n >> m ;
  56. for(int i=1;i<=m;i++){
  57. x = read() ; y = read() ;
  58. // cin >> x >> y ;
  59. a[x].push_back(y);
  60. }
  61. for(int i=1;i<=n;i++) sort(a[i].begin(),a[i].end()); // 将每条路通向的点从小到大排序
  62. dfs(1,0) ; // 深搜
  63. puts("");
  64. for(int i=1;i<=n;i++) b[i] = false ;
  65. bfs(1) ; // 宽搜
  66. puts("") ;
  67. return 0;
  68. }

B3644 【模板】拓扑排序 / 家谱树

链接 :

 https://www.luogu.com.cn/problem/B3644

思路 : 

给出案例画图如下 : 

拓扑排序(模板题)

代码 : 

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 102 ;
  4. vector<int> a[N] ;
  5. int tp[N] ; // 存放拓扑序列
  6. int d[N] ; // 存放每个结点的入度
  7. int n , x ;
  8. bool toposort() {
  9. queue<int> q;
  10. int tt = 0 ;
  11. for(int i = 1; i <= n; i++) {
  12. if(d[i] == 0) {
  13. q.push(i); // 将入度为 0 的点全放进来
  14. }
  15. }
  16. while(!q.empty()) {
  17. int u = q.front() ; q.pop();
  18. tp[++tt] = u ;
  19. for(auto v : a[u]) {
  20. d[v] -- ;
  21. if(d[v] == 0){
  22. q.push(v);
  23. }
  24. }
  25. }
  26. return tt == n;
  27. }
  28. int main(){
  29. scanf("%d",&n);
  30. for(int i=1;i<=n;i++){
  31. while(cin >> x){
  32. if(x == 0) break;
  33. a[i].push_back(x);
  34. d[x] ++;
  35. }
  36. }
  37. if(toposort()) {
  38. for(int i=1;i<=n;i++){
  39. cout << tp[i] << " ";
  40. }
  41. cout << endl ;
  42. }
  43. else{
  44. return 0;
  45. }
  46. return 0 ;
  47. }

或者说这样 : 

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 102 ;
  4. vector<int> a[N] ;
  5. int d[N] ; // 存放每个结点的入度
  6. int n , x ;
  7. bool toposort() {
  8. queue<int> q;
  9. vector<int> res;
  10. for(int i = 1; i <= n; i++) {
  11. if(d[i] == 0) {
  12. q.push(i); // 将入度为 0 的点全放进来
  13. }
  14. }
  15. while(!q.empty()) {
  16. int u = q.front() ; q.pop();
  17. res.push_back(u);
  18. for(auto v : a[u]) {
  19. d[v] -- ;
  20. if(d[v] == 0){
  21. q.push(v);
  22. }
  23. }
  24. }
  25. if(res.size()==n) {
  26. for(auto x : res) cout << x << " ";
  27. return true;
  28. }else {
  29. return false;
  30. }
  31. }
  32. int main(){
  33. scanf("%d",&n);
  34. for(int i=1;i<=n;i++){
  35. while(cin >> x){
  36. if(x == 0) break;
  37. a[i].push_back(x);
  38. d[x] ++;
  39. }
  40. }
  41. if(toposort()) {
  42. return 0 ;
  43. }
  44. return 0 ;
  45. }

P3916 图的遍历

链接 : 

图的遍历 - 洛谷

思路 : 

反向建边 + dfs : 

代码 : 

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 10 ;
  4. vector<int> g[N] ;
  5. int n , m ;
  6. int ans[N] ;
  7. // 反向建图 + dfs
  8. // 考虑较大的点能够法相到达那一些点
  9. void dfs(int i , int b){
  10. if(ans[i]) return ;
  11. ans[i] = b ;
  12. for(int j=0;j<g[i].size();j++){
  13. dfs(g[i][j] , b) ;
  14. }
  15. }
  16. int main(){
  17. cin >> n >> m ;
  18. for(int i=0;i<m;i++){
  19. int x , y ; cin >> x >> y ;
  20. g[y].push_back(x) ; // 反向建边
  21. }
  22. for(int i=n;i;i--) dfs(i,i) ; // 对i进行dfs
  23. for(int i=1;i<=n;i++){
  24. cout << ans[i] << " " ;
  25. // if(ans[i]) cout << ans[i] << endl ;
  26. // else cout << i << endl ;
  27. }
  28. return 0;
  29. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/886799
推荐阅读
相关标签
  

闽ICP备14008679号