[关闭]
@Pinetrie 2019-01-30T03:34:32.000000Z 字数 2877 阅读 889

A - 拓扑排序

题意:有一些任务要完成,但是有部分任务不能直接去做,要先完成某些前置任务才可以 开始做。要求输入一个完成所有任务的合法顺序。

题解:直接按拓扑排序的方法来做,先输出入读为0的点,再把这个点从图中删去,同时与这个点相连的其他点的入度减小。重复这个过程直到所有点都输出。

  1. #include <stdio.h>
  2. #include <vector>
  3. #include <cstring>
  4. #include <queue>
  5. using namespace std;
  6. int n,m,in_du[110];
  7. vector<int>G[110];
  8. queue<int>Q;
  9. void topsort()
  10. {
  11. while(!Q.empty())
  12. {
  13. int u = Q.front();
  14. Q.pop();
  15. printf("%d ",u);
  16. for(int i = 0;i < (int)G[u].size();i++)
  17. {
  18. int v = G[u][i];
  19. in_du[u]--,in_du[v]--;
  20. if(in_du[v] == 0)
  21. {
  22. Q.push(v);
  23. }
  24. }
  25. }
  26. }
  27. int main()
  28. {
  29. while(scanf("%d %d",&n,&m) && (n || m))
  30. {
  31. for(int i = 0;i <= n;i++) G[i].clear();
  32. memset(in_du,0,sizeof(in_du));
  33. for(int i = 1;i <= m;i++)
  34. {
  35. int u,v;
  36. scanf("%d %d",&u,&v);
  37. G[u].push_back(v);
  38. in_du[v]++;
  39. }
  40. for(int i = 1;i <= n;i++)
  41. {
  42. if(in_du[i] == 0)
  43. Q.push(i);
  44. }
  45. topsort();
  46. printf("\n");
  47. }
  48. return 0;
  49. }

B - 欧拉路

题意:给出一些单词,判断这些单词能不能首尾相接连在一起,当一个单词的尾字母和另一个单词的首字母相同时可以接在一起。

题解:把单词的首尾字母抽象成点,然后判断能不能形成欧拉图或者半欧拉图。有向图形成欧拉图的条件是每个点的出度都等于入读,形成半欧拉图的条件是起点的出度减入读等于一,终点的入读减出度等于一,其他点的出度和入读相同。同时还需要是一个连通图。不满足以上条件的都不成立。

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <cstring>
  5. using namespace std;
  6. int fa[26],vis[26],in[26],out[26],n;
  7. int Find(int x)
  8. {
  9. if(x == fa[x]) return x;
  10. else return fa[x] = Find(fa[x]);
  11. }
  12. void Union(int x,int y)
  13. {
  14. int fx = Find(x),fy = Find(y);
  15. if(fx != fy) fa[fx] = fy;
  16. }
  17. int main()
  18. {
  19. int T;
  20. scanf("%d",&T);
  21. while(T--)
  22. {
  23. memset(vis,0,sizeof(vis));
  24. memset(out,0,sizeof(out));
  25. memset(in,0,sizeof(in));
  26. for(int i = 0;i < 26;i++) fa[i] = i;
  27. scanf("%d",&n);
  28. string s;
  29. for(int i = 1;i <= n;i++)
  30. {
  31. cin>>s;
  32. char fi = s[0];
  33. char se = s[s.size() - 1];
  34. vis[fi - 'a'] = 1,vis[se - 'a'] = 1;
  35. out[fi - 'a']++,in[se - 'a']++;
  36. Union(fi - 'a',se - 'a');
  37. }
  38. int flag = 1,root = 0;
  39. for(int i = 0;i < 26;i++)
  40. {
  41. if(vis[i] == 1 && Find(i) == i)
  42. root++;
  43. }
  44. if(root > 1)
  45. {
  46. printf("The door cannot be opened.\n");
  47. continue;
  48. }
  49. int st = 0,ed = 0;
  50. for(int i = 0;i < 26;i++)
  51. {
  52. if(vis[i] == 1 && out[i] != in[i])
  53. {
  54. if(in[i] - out[i] == 1) ed++;
  55. else if(in[i] - out[i] == -1) st++;
  56. else flag = 0;
  57. }
  58. }
  59. if(!((st == 1 && ed == 1) || (st == 0 && ed == 0))) flag = 0;
  60. if(flag == 0) printf("The door cannot be opened.\n");
  61. else printf("Ordering is possible.\n");
  62. }
  63. return 0;
  64. }

C - 欧拉路

题意:一个房子里有编号为0到n-1的n个房间,有一些房间的门是开着的,给出起点房间及每个开着门的房间与其他开着门的房间相连的情况,问能不能经过所有门一次最后回到0号房间。如果能输出经过的门的数量。

题解:这道题的正确做法应该是需要判是否连通的,但是我判了连通后wa了,然后不判连通就ac了,去网上找判连通a了的代码也没找到。那如果在已知连通的情况下判断就是要么从0出发再回到0,那么是判欧拉图。或者从其他点出发再回到0,那么就是判半欧拉图。无向图判断欧拉图的条件是每个点的度数为偶数。半欧拉图的条件是起点和终点的度数为奇数,其他点的度数为偶数。

  1. //AC代码,但是没有判连通//
  2. #include <cstdio>
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <cstring>
  6. using namespace std;
  7. int st,n,du[110];
  8. char str[110];
  9. int main()
  10. {
  11. string s;
  12. while(cin>>s)
  13. {
  14. int num = 0;
  15. if(s == "ENDOFINPUT") break;
  16. if(s == "END") continue;
  17. if(s == "START") scanf("%d %d",&st,&n);
  18. memset(du,0,sizeof(du));
  19. getchar();
  20. for(int i = 0;i < n;i++)
  21. {
  22. gets(str);
  23. int cont = 0;
  24. for(int j = 0;j <= (int)strlen(str);j++)
  25. {
  26. if(str[j] >= '0' && str[j] <= '9') cont = cont * 10 + str[j] - '0';
  27. else
  28. {
  29. if(cont > 0)
  30. {
  31. du[i]++;
  32. du[cont]++;
  33. num++;
  34. cont = 0;
  35. }
  36. }
  37. }
  38. }
  39. int flag = 1;
  40. if(st == 0)
  41. {
  42. for(int i = 0;i < n;i++)
  43. {
  44. if(du[i] % 2 == 1) flag = 0;
  45. }
  46. if(flag == 0) printf("NO\n");
  47. else printf("YES %d\n",num);
  48. }
  49. else
  50. {
  51. int cont = 0;
  52. for(int i = 0;i < n;i++)
  53. {
  54. if(i == 0 && du[i] % 2 != 1) flag = 0;
  55. if(i > 0 && du[i] % 2 == 1) cont++;
  56. }
  57. if(cont != 1) flag = 0;
  58. if(flag == 0) printf("NO\n");
  59. else printf("YES %d\n",num);
  60. }
  61. }
  62. return 0;
  63. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注