鱼C论坛

 找回密码
 立即注册
查看: 2831|回复: 5

修路问题

[复制链接]
发表于 2021-11-14 22:00:23 | 显示全部楼层 |阅读模式
1鱼币
畅通工程
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

Input
测试输入包含若干测试用例。每个测试用例的第1行给出一个正整数和一个非负整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 注意:两个城市之间可以有多条道路相通,也就是说 3 3 1 2 1 2 2 1 这种输入也是合法的 当N为0时,输入结束,该用例不被处理。

Output
对每个测试用例,在1行里输出最少还需要建设的道路数目。

输入示例
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
输出示例
1
0
2
998

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-11-15 19:32:51 | 显示全部楼层
本帖最后由 jhq999 于 2021-11-15 19:34 编辑

输入示例和题目不符,N在哪?M在哪?才明白原来是4个示例
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-11-15 20:52:25 | 显示全部楼层
本帖最后由 jhq999 于 2021-11-15 22:01 编辑
  1. #include<stdio.h>
  2. #include<stdlib.h>

  3. void roadoutput(int (*road)[3],int m,int n)
  4. {
  5.         int i=0,j=0,count=0;
  6.         for (i = 1; i <= n; i++)//找出没通路的
  7.         {
  8.                 for (j = 0; j < m; j++)
  9.                 {
  10.                         if (i==road[j][0]||i==road[j][1])
  11.                         {
  12.                                 break;;
  13.                         }
  14.                 }
  15.                 if (j==m)
  16.                 {
  17.                         count++;
  18.                 }
  19.         }
  20.         for (i = 0; i < m; i++)//把互通的找出来算成一个孤立的城镇
  21.         {
  22.                 if (!road[i][2])
  23.                 {
  24.                         road[i][2]=1;
  25.                         count++;

  26.                         for (j = i+1; j < m; j++)
  27.                         {
  28.                                 if (!road[j][2])
  29.                                 {
  30.                                         if ((road[i][0]==road[j][0])||(road[i][1]==road[j][0])\
  31.                                                 ||(road[i][0]==road[j][1])||(road[i][1]==road[j][1]))
  32.                                         {
  33.                                                 road[j][2]=1;
  34.                                         }
  35.                                 }
  36.                         }
  37.                 }
  38.         }

  39.         printf("%d\n",count-1);//孤立的城镇互通最少的路的条数是孤立的城镇数量-1
  40.        

  41. }

  42. int main()
  43. {

  44.         int i=0,j=0,n=0,m=0;
  45.         while (1)
  46.         {
  47.                 scanf("%d",&n);
  48.                 if (!n)
  49.                 {
  50.                         break;
  51.                 }
  52.                 scanf("%d",&m);
  53.                 int (*road)[3]=(int(*)[3])malloc(m*3*sizeof(int));
  54.                 for (i = 0; i <m; i++)
  55.                 {
  56.                         scanf("%d %d",&road[i][0],&road[i][1]);
  57.                         road[i][2]=0;
  58.                         fflush(stdin);
  59.                 }
  60.                 roadoutput(road,m,n);
  61.                 free(road);

  62.         }
  63.         return 0;
  64. }
复制代码
  1. 10 4
  2. 1 2
  3. 3 4
  4. 5 6
  5. 9 10
  6. 5
  7. 10 6
  8. 1 2
  9. 1 3
  10. 2 3
  11. 4 5
  12. 8 9
  13. 9 10
  14. 4
  15. 4 2
  16. 1 3
  17. 4 3
  18. 1
  19. 3 3
  20. 1 2
  21. 1 3
  22. 2 3
  23. 0
  24. 5 2
  25. 1 2
  26. 3 5
  27. 2
  28. 999 0
  29. 998
  30. 0
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-11-16 00:57:19 | 显示全部楼层
  1. #include<stdio.h>

  2. void RoadNum(void);        

  3. int main(void)
  4. {
  5.         RoadNum();
  6.        
  7.         return 0;
  8. }

  9. void RoadNum(void)        //该函数用来实现修路问题,整体思想为n个城镇至少需要n-1条有效路径。m是现存的路径,需要判断里面是否有无效路径,比如同时存在1 2 2 1。
  10. {
  11.         int n, m;         // n为城镇数量,m 为现存路径。
  12.         int count = 0; //用来统计m中的无效路径。
  13.         int i, k;         //用来循环
  14.         int j= 0;        //用来存储还需要几条路。
  15.         int road[100]; // 将还需要几条路存储在road数组中。
  16.        
  17.         printf("请输入城镇和道路信息:\n");
  18.         while (1)
  19.         {
  20.                 count = 0;        //辅助统计现有多少条路。
  21.                 scanf("%d", &n);
  22.                 if (n == 0) // 设置循环终止条件,输入0结束。
  23.                 {
  24.                         break;
  25.                 }
  26.                 scanf("%d", &m);
  27.                
  28.                 struct Exist         // 每一条路是两个城镇来表示,因此定义了一个结构体来表示。
  29.                 {
  30.                         int t1;
  31.                         int t2;
  32.                 };
  33.                
  34.                 struct Exist exi[m];         // 现存m条路因此定义了一个exi[m]的数组,来存放。
  35.                
  36.                 for (i = 0; i < m; i++)                //输入城镇和道路信息;
  37.                 {
  38.                         scanf("%d%d", &(exi[i].t1), &(exi[i].t2));
  39.                         if (exi[i].t1 > n || exi[i].t2 > n) //假如5个城镇的话,用1,2,3,4,5来表示,输入的数字不能超过5,否则报错。
  40.                         {
  41.                                 printf("输入错误\n");
  42.                                 return;
  43.                         }
  44.                 }
  45.                
  46.                 for (i = 0; i < m; i++) // 无效路径的判断。
  47.                 {
  48.                         for (k = i+1; k < m; k++)
  49.                         {
  50.                                 if ((exi[i].t1 == exi[k].t1 && exi[i].t2 == exi[k].t2) || (exi[i].t1 = exi[k].t2 && exi[i].t2 == exi[k].t1))
  51.                                 {
  52.                                         count++;
  53.                                         break; //非常重要,防止重复计数。
  54.                                 }
  55.                         }
  56.                 }
  57.                
  58.                 road[j++] = (n-1) - (m-count);         // n-1为需要的路径,m-count为现有的有效路径。
  59.         }
  60.        
  61.         printf("输出结果\n");
  62.        
  63.         for (i = 0; i < j; i++)
  64.         {
  65.                 printf("%d\n", road[i]);
  66.         }
  67.        
  68.         return;
  69. }
复制代码

结果显示:
请输入城镇和道路信息:
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
输出结果
1
0
2
998

--------------------------------
Process exited after 11.71 seconds with return value 0
请按任意键继续. . .
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-11-16 12:22:39 | 显示全部楼层
  1. #include <iostream>

  2. using namespace std;

  3. typedef struct ufset *UFset;
  4. typedef struct ufset
  5. {
  6.         int *parent;
  7.         int *root;
  8. }UFS;

  9. UFset UFinit(int size)
  10. {
  11.         UFset U = new ufset;
  12.         U->parent = new int[size+1];
  13.         U->root = new int[size+1];
  14.         for (int e = 1; e <= size; e++)
  15.         {
  16.                 U->parent[e] = 1;
  17.                 U->root[e] = 1;
  18.         }
  19.         return U;
  20. }

  21. int UFfind(int e, UFset U)
  22. {
  23.         int i, j = e;
  24.         while ( !U->root[j] )
  25.         {
  26.                 j = U->parent[j];
  27.         }
  28.         while ( j != e )
  29.         {
  30.                 i = U->parent[e];
  31.                 U->parent[e] = j;
  32.                 e = i;
  33.         }
  34.         return j;
  35. }

  36. int UFunion(int i, int j, UFset U)
  37. {
  38.         if (i == j) return i;
  39.         if (U->parent[i] < U->parent[j])
  40.         {
  41.                 U->parent[j] += U->parent[i];
  42.                 U->root[i] = 0;
  43.                 U->parent[i] = j;
  44.                 return j;
  45.         }
  46.         else {
  47.                 U->parent[i] += U->parent[j];
  48.                 U->root[j] = 0;
  49.                 U->parent[j] = i;
  50.                 return i;
  51.         }
  52. }

  53. void UFfree(UFset U)
  54. {
  55.         delete [] U->parent;
  56.         delete [] U->root;
  57.         delete U;
  58. }

  59. void uni(int x, int y, UFset uf)
  60. {
  61.         int a = UFfind(x, uf),
  62.                 b = UFfind(y, uf);
  63.         UFunion(a, b, uf);
  64. }

  65. int main()
  66. {
  67.         int N, M, index1, index2, count;
  68.        
  69.         UFset uf;
  70.        
  71.         while (true)
  72.         {
  73.                 count = 0;
  74.                 cin >> N;
  75.                 if ( N == 0 ) break;
  76.                 cin >> M;
  77.                
  78.                 uf = UFinit(N);
  79.                
  80.                 for (int i = 0; i < M; i++)
  81.                 {
  82.                         cin >> index1 >> index2;
  83.                         uni(index1, index2, uf);
  84.                 }
  85.                 for (int i = 1; i <= N; i++)
  86.                 {
  87.                         int j = UFfind(i, uf);
  88.                         if ( i == j ) count++;
  89.                 }
  90.                 cout << count - 1 << endl;
  91.                
  92.                 UFfree(uf);
  93.         }
  94. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-11-16 12:23:37 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-25 13:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表