当前位置:   article > 正文

ZISUOJ 数据结构--图及其应用

ZISUOJ 数据结构--图及其应用

说明

        主要考察建图,图的遍历以及求最小生成树。都还是比较简单的,后面就直接上代码了。

        最小生成树采用prim还是kruskal算法要看题目怎么给出数据,如果以邻接矩阵的形式给出,采用prim算法比较合适,如果以边和边的权重的形式给出,则采用kruskal算法比较合适。例如这里的D和E题采用kruskal算法比较好,但是不代表用prim算法不能做,我这两个题给出的就是prim的解法,但是某些题用另一个算法极不方便,因此还是建议采用题目所暗示我们应使用的方法最佳。

题目列表

问题 A: 图的遍历—深度优先搜索—邻接矩阵

参考题解:

  1. #include <iostream>
  2. #include <functional>
  3. int main(){
  4. std::cin.tie(nullptr)->sync_with_stdio(false);
  5. constexpr int MAX_N = 5e1+5;
  6. int g[MAX_N][MAX_N] {};
  7. bool vis[MAX_N] {};
  8. int n;std::cin >> n;
  9. for(int i = 0;i<n;i++){
  10. for(int j = 0;j<n;j++){
  11. std::cin >> g[i][j];
  12. }
  13. }
  14. using Dfs = std::function<void(int)>;
  15. Dfs dfs = [&](int u) {
  16. std::cout << u << ' ';
  17. for(int i = 0;i<n;i++){
  18. if(g[u][i]&&!vis[i]) vis[i]=true,dfs(i);
  19. }
  20. };
  21. vis[0] = true;
  22. dfs(0);
  23. std::cout << '\n';
  24. return 0;
  25. }

问题 B: 图的遍历—DFS—已知边

参考题解:

  1. #include <iostream>
  2. #include <functional>
  3. int main(){
  4. std::cin.tie(nullptr)->sync_with_stdio(false);
  5. constexpr int MAX_N = 1e1+5;
  6. int g[MAX_N][MAX_N] {};
  7. bool vis[MAX_N] {};
  8. int n,m;std::cin >> n >> m;
  9. while(m--){
  10. int x,y;std::cin >> x >> y;
  11. g[x][y]=g[y][x]=1;
  12. }
  13. using Dfs = std::function<void(int)>;
  14. Dfs dfs = [&](int u){
  15. std::cout << u << ' ';
  16. for(int i = 1;i<=n;i++){
  17. if(g[u][i]&&!vis[i]) vis[i]=true,dfs(i);
  18. }
  19. };
  20. vis[1] = true;
  21. dfs(1);
  22. std::cout << '\n';
  23. return 0;
  24. }

问题 C: 图的遍历—广度优先搜索

参考题解:

  1. #include <iostream>
  2. #include <queue>
  3. int main(){
  4. std::cin.tie(nullptr)->sync_with_stdio(false);
  5. constexpr int MAX_N = 5e1+5;
  6. int g[MAX_N][MAX_N] {};
  7. bool vis[MAX_N] {};
  8. int n;std::cin >> n;
  9. for(int i = 0;i<n;i++){
  10. for(int j = 0;j<n;j++){
  11. std::cin >> g[i][j];
  12. }
  13. }
  14. auto bfs = [&](){
  15. std::queue<int> q;
  16. q.emplace(0);
  17. vis[0] = true;
  18. while(!q.empty()){
  19. auto t = q.front();
  20. q.pop();
  21. std::cout << t << ' ';
  22. for(int i = 0;i<n;i++){
  23. if(!vis[i]&&g[t][i]){
  24. vis[i] = true;
  25. q.emplace(i);
  26. }
  27. }
  28. }
  29. };
  30. bfs();
  31. std::cout << '\n';
  32. return 0;
  33. }

问题 D: 最小生成树-局域网

 

参考题解:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <type_traits>
  4. template<typename T1,typename T2>
  5. typename std::common_type<T1,T2>::type min(T1 num1,T2 num2){
  6. return num1>num2?num2:num1;
  7. }
  8. int main(){
  9. std::cin.tie(nullptr)->sync_with_stdio(false);
  10. constexpr int MAX_N = 1e2+5,INF = 0x3f3f3f3f;
  11. int g[MAX_N][MAX_N];
  12. int dist[MAX_N];
  13. memset(g,0x3f,sizeof g);
  14. bool vis[MAX_N] = {false};
  15. int n,m;std::cin >> n >> m;
  16. int ans = 0;
  17. while(m--){
  18. int x,y,w;std::cin >> x >> y >> w;
  19. g[x][y]=g[y][x]=min(g[y][x],w);
  20. ans+=w;
  21. }
  22. auto prim = [&]()->int{
  23. memset(dist,0x3f,sizeof dist);
  24. dist[1] = 0;
  25. int ans = 0;
  26. for(int i = 0;i<n;++i){
  27. int t = -1;
  28. for(int j = 1;j<=n;++j){
  29. if(!vis[j]&&(t==-1||dist[t]>dist[j])) t = j;
  30. }
  31. if(dist[t]==INF) return INF;
  32. ans+=dist[t];
  33. vis[t] = true;
  34. for(int j = 1;j<=n;++j) dist[j] = min(dist[j],g[t][j]);
  35. }
  36. return ans;
  37. };
  38. ans-=prim();
  39. std::cout << ans << '\n';
  40. return 0;
  41. }

问题 E: 最小生成树-繁忙的都市

 

参考题解:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <type_traits>
  4. template<typename T1,typename T2>
  5. typename std::common_type<T1,T2>::type max(T1 num1,T2 num2){
  6. return num1<num2?num2:num1;
  7. }
  8. template<typename T1,typename T2>
  9. typename std::common_type<T1,T2>::type min(T1 num1,T2 num2){
  10. return num1>num2?num2:num1;
  11. }
  12. int main(){
  13. std::cin.tie(nullptr)->sync_with_stdio(false);
  14. constexpr int MAX_N = 1e2+5,INF = 0x3f3f3f3f;
  15. int g[MAX_N][MAX_N];
  16. int dist[MAX_N];
  17. memset(g,0x3f,sizeof g);
  18. bool vis[MAX_N] = {false};
  19. int n,m;std::cin >> n >> m;
  20. while(m--){
  21. int x,y,w;std::cin >> x >> y >> w;
  22. g[x][y]=g[y][x]=min(g[y][x],w);
  23. }
  24. auto prim = [&]()->int{
  25. memset(dist,0x3f,sizeof dist);
  26. dist[1] = 0;
  27. int ans = 0;
  28. for(int i = 0;i<n;++i){
  29. int t = -1;
  30. for(int j = 1;j<=n;++j){
  31. if(!vis[j]&&(t==-1||dist[t]>dist[j])) t = j;
  32. }
  33. if(dist[t]==INF) return INF;
  34. ans = max(ans,dist[t]);
  35. vis[t] = true;
  36. for(int j = 1;j<=n;++j) dist[j]=min(dist[j],g[t][j]);
  37. }
  38. return ans;
  39. };
  40. std::cout << n-1 << ' ' << prim() << '\n';
  41. return 0;
  42. }

问题 F: 最小生成树-联络员

 

参考题解:

  1. #include <iostream>
  2. #include <vector>
  3. #include <functional>
  4. #include <algorithm>
  5. constexpr int MAX_N = 2e3+5,MAX_M = 1e4+5,INF = 0x3f3f3f3f;
  6. struct edge{
  7. int x,y,w;
  8. bool operator < (const edge& W){
  9. return w<W.w;
  10. }
  11. edge(int _x,int _y,int _w):x(_x),y(_y),w(_w){}
  12. };
  13. std::vector<edge> edges;
  14. int fa[MAX_N];
  15. int main(){
  16. std::cin.tie(nullptr)->sync_with_stdio(false);
  17. int n,m;std::cin >> n >> m;
  18. for(int i = 1;i<=n;++i) fa[i] = i;
  19. using Find = std::function<int(int)>;
  20. Find find = [&](int x){
  21. if(x!=fa[x]) fa[x] = find(fa[x]);
  22. return fa[x];
  23. };
  24. int ans = 0;
  25. while(m--){
  26. int t,x,y,w;std::cin >> t >> x >> y >> w;
  27. if(t==1){
  28. ans+=w;
  29. fa[find(x)] = find(y);
  30. }else{
  31. edges.emplace_back(x,y,w);
  32. }
  33. }
  34. auto kruskal = [&](){
  35. std::sort(edges.begin(),edges.end());
  36. for(int i = 0;i<edges.size();++i){
  37. int fx = find(edges[i].x),fy = find(edges[i].y),w = edges[i].w;
  38. if(fx!=fy){
  39. fa[fx] = fy;
  40. ans+=w;
  41. }
  42. }
  43. };
  44. kruskal();
  45. std::cout << ans << '\n';
  46. return 0;
  47. }

问题 G: 最小生成树-连接格点

 

参考题解:

  1. #include <iostream>
  2. #include <functional>
  3. constexpr int MAX_N = 1e3+5;
  4. int fa[MAX_N*MAX_N];
  5. int main(){
  6. std::cin.tie(nullptr)->sync_with_stdio(false);
  7. using Find = std::function<int(int)>;
  8. Find find = [&](int x)->int{
  9. if(x!=fa[x]) fa[x] = find(fa[x]);
  10. return fa[x];
  11. };
  12. int n,m;std::cin >> n >> m;
  13. for(int i = 0;i<=n*m;++i) fa[i] = i;
  14. int x1,y1,x2,y2;
  15. while(std::cin >> x1 >> y1 >> x2 >> y2){
  16. fa[find((x1-1)*m+y1)] = find((x2-1)*m+y2);
  17. }
  18. int ans = 0;
  19. auto kruskal = [&]()->void{
  20. for(int i = 1;i<n;++i){
  21. for(int j = 1;j<=m;++j){
  22. int dx = find((i-1)*m+j),dy = find(i*m+j);
  23. if(dx!=dy){
  24. ++ans;
  25. fa[dx] = dy;
  26. }
  27. }
  28. }
  29. for(int i = 1;i<=n;++i){
  30. for(int j = 1;j<m;++j){
  31. int dx = find((i-1)*m+j),dy = find((i-1)*m+j+1);
  32. if(dx!=dy){
  33. ans+=2;
  34. fa[dx] = dy;
  35. }
  36. }
  37. }
  38. };
  39. kruskal();
  40. std::cout << ans << '\n';
  41. return 0;
  42. }

问题 H: 最小生成树-最短网络

 

参考题解:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <type_traits>
  4. template<typename T1,typename T2>
  5. typename std::common_type<T1,T2>::type min(T1 num1,T2 num2){
  6. return num1>num2?num2:num1;
  7. }
  8. int main(){
  9. std::cin.tie(nullptr)->sync_with_stdio(false);
  10. constexpr int MAX_N = 1e2+5,INF = 0x3f3f3f3f;
  11. int g[MAX_N][MAX_N];
  12. int dist[MAX_N];
  13. bool vis[MAX_N] {};
  14. int n;std::cin >> n;
  15. for(int i = 1;i<=n;++i){
  16. for(int j = 1;j<=n;++j){
  17. std::cin >> g[i][j];
  18. }
  19. }
  20. auto prim = [&]()->int{
  21. memset(dist,0x3f,sizeof dist);
  22. int res = 0;
  23. dist[1] = 0;
  24. for(int i = 0;i<n;++i){
  25. int t = -1;
  26. for(int j = 1;j<=n;++j){
  27. if(!vis[j]&&(t==-1||dist[j]<dist[t])) t = j;
  28. }
  29. if(dist[t]==INF) return INF;
  30. vis[t] = true;
  31. res+=dist[t];
  32. for(int j = 1;j<=n;++j) dist[j]=min(dist[j],g[t][j]);
  33. }
  34. return res;
  35. };
  36. std::cout << prim() << '\n';
  37. return 0;
  38. }

问题 I: 最小生成树-最优布线问题

 

参考题解:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <type_traits>
  4. template<typename T1,typename T2>
  5. typename std::common_type<T1,T2>::type min(T1 num1,T2 num2){
  6. return num1>num2?num2:num1;
  7. }
  8. int main(){
  9. std::cin.tie(nullptr)->sync_with_stdio(false);
  10. constexpr int MAX_N = 1e2+5,INF = 0x3f3f3f3f;
  11. int g[MAX_N][MAX_N];
  12. int dist[MAX_N];
  13. bool vis[MAX_N] {};
  14. int n;std::cin >> n;
  15. for(int i = 1;i<=n;++i){
  16. for(int j = 1;j<=n;++j){
  17. std::cin >> g[i][j];
  18. }
  19. }
  20. auto prim = [&]()->int{
  21. memset(dist,0x3f,sizeof dist);
  22. int res = 0;
  23. dist[1] = 0;
  24. for(int i = 0;i<n;++i){
  25. int t = -1;
  26. for(int j = 1;j<=n;++j){
  27. if(!vis[j]&&(t==-1||dist[j]<dist[t])) t = j;
  28. }
  29. if(dist[t]==INF) return INF;
  30. vis[t] = true;
  31. res+=dist[t];
  32. for(int j = 1;j<=n;++j) dist[j]=min(dist[j],g[t][j]);
  33. }
  34. return res;
  35. };
  36. std::cout << prim() << '\n';
  37. return 0;
  38. }

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

闽ICP备14008679号