[关闭]
@iamtts 2017-02-10T15:42:57.000000Z 字数 3897 阅读 976

寒假第五次训练-欧拉回路&拓扑排序

A - 确定比赛名次

题目大意:有n支队伍比赛,已知m组形如:a b的数据,表示a战胜了b,求所有队伍的排名顺序,且序号小的队伍排名在前

解题思路:拓扑排序,需要注意的是在每搜索到一个入度为0的点且削减完与它连接的点的入度就重新循环,保证序号小的在前。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. using namespace std;
  10. #define MAXN 505
  11. int indegree[MAXN],topo[MAXN],n,m;
  12. int G[MAXN][MAXN];
  13. void toposort()
  14. {
  15. int u,v,i,t=0;
  16. memset(topo,0,sizeof(topo));
  17. for (i=0; i<n; i++)
  18. {
  19. for (u=1; u<=n; u++)
  20. {
  21. if (indegree[u]==0)
  22. {
  23. indegree[u]=-1;
  24. topo[t++]=u;
  25. for (v=1; v<=n; v++)
  26. {
  27. if (G[u][v]) indegree[v]--;
  28. }
  29. break;
  30. }
  31. }
  32. }
  33. }
  34. int main()
  35. {
  36. int u,v;
  37. while(~scanf("%d%d",&n,&m))
  38. {
  39. memset(G,0,sizeof(G));
  40. memset(indegree,0,sizeof(indegree));
  41. for (int i=0; i<m; i++)
  42. {
  43. scanf("%d%d",&u,&v);
  44. if (G[u][v]==0)
  45. {
  46. G[u][v]=1;
  47. indegree[v]++;
  48. }
  49. }
  50. toposort();
  51. for (int i=0; i<n; i++)
  52. printf("%d%c",topo[i],i==n-1?'\n':' ');
  53. }
  54. }

B - Reward

题目大意:有n个工人,他们需要从老板那里拿工资,然后提出了m个要求,形如:a b,表示a要求工资比b高,每个人基准工资为888,求老板需支出的最小工资

解题思路:数据较大,用邻接表(vector)存储,a比b工资高则a的入度增加,从入度为0的基准工资(888)开始拓扑排序,最后加和。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. using namespace std;
  10. #define MAXN 10005
  11. int indegree[MAXN],a[MAXN],n,m;
  12. vector<int> G[MAXN];
  13. stack<int> temp;
  14. void toposort()
  15. {
  16. int u,v,i,t=0,rec=n,sum=0;
  17. memset(a,0,sizeof(a));
  18. for (i=0; i<n; i++)
  19. {
  20. for (u=1; u<=n; u++)
  21. {
  22. if (indegree[u]==0)
  23. {
  24. temp.push(u);
  25. indegree[u]=-1;
  26. a[u]=i;
  27. rec--;
  28. }
  29. }
  30. while (!temp.empty())
  31. {
  32. u=temp.top();
  33. temp.pop();
  34. for (v=0; v<G[u].size(); v++)
  35. {
  36. indegree[G[u][v]]--;
  37. }
  38. }
  39. }
  40. if (rec==0)
  41. {
  42. for (int i=1;i<=n;i++)
  43. sum+=a[i];
  44. printf("%d\n",888*n+sum);
  45. }
  46. else
  47. {
  48. printf("-1\n");
  49. }
  50. }
  51. int main()
  52. {
  53. int u,v;
  54. while(~scanf("%d%d",&n,&m))
  55. {
  56. memset(indegree,0,sizeof(indegree));
  57. for (int i=0; i<=n; i++)
  58. G[i].clear();
  59. for (int i=0; i<m; i++)
  60. {
  61. scanf("%d%d",&u,&v);//v比u工资低
  62. G[v].push_back(u);
  63. indegree[u]++;
  64. }
  65. toposort();
  66. }
  67. }

D - 欧拉回路

题目大意:欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?

解题思路:欧拉回路要满足:1.图是联通的;2.每个点连线数为偶数

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. using namespace std;
  10. #define MAXN 1005
  11. int degree[MAXN],n,m;
  12. int G[MAXN][MAXN];
  13. bool judge()
  14. {
  15. int i,j;
  16. for (i=1; i<=n; i++)
  17. {
  18. if (degree[i]%2!=0) return false;
  19. for (j=1; j<=n; j++)
  20. {
  21. if (i!=j && G[i][j]!=1) return false;
  22. }
  23. }
  24. return true;
  25. }
  26. int main()
  27. {
  28. int u,v;
  29. while(scanf("%d",&n),n)
  30. {
  31. scanf("%d",&m);
  32. memset(G,0,sizeof(G));
  33. memset(degree,0,sizeof(degree));
  34. for (int i=0; i<m; i++)
  35. {
  36. scanf("%d%d",&u,&v);
  37. if (G[u][v]==0)
  38. {
  39. G[v][u]=G[u][v]=1;
  40. degree[v]++;
  41. degree[u]++;
  42. }
  43. }
  44. if (judge()) printf("1\n");
  45. else printf("0\n");
  46. }
  47. }

E - Play on Words

题目大意:给定n个单词,判断是否可以适当排序使之首尾相连,如:acm与mouse就可以连接

解题思路:单词的首尾字母作为节点,中间部分作为连线,划为欧拉道路问题来解决,用并查集判断是否联通

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. using namespace std;
  10. #define MAXN 100005
  11. int indegree[27],outdegree[27],n;
  12. int count_;
  13. int par[27],rank_[27];
  14. bool hash_[27];
  15. void init()
  16. {
  17. int i;
  18. for (i=0;i<26;i++)
  19. par[i]=i;
  20. rank_[i]=0;
  21. }
  22. int find_(int x)
  23. {
  24. if (par[x]==x) return x;
  25. else return par[x]=find_(par[x]);
  26. }
  27. void unite(int x,int y)
  28. {
  29. x=find_(x);
  30. y=find_(y);
  31. if (x==y) return;
  32. if (rank_[x]<rank_[y])
  33. par[x]=y;
  34. else
  35. {
  36. par[y]=x;
  37. if (rank_[x]==rank_[y]) rank_[x]++;
  38. }
  39. count_--;
  40. }
  41. bool judge()
  42. {
  43. int i,j,rec=0,flag1=0,flag2=0;
  44. for (i=0;i<26;i++)
  45. {
  46. if (indegree[i]!=outdegree[i])
  47. {
  48. rec++;
  49. if (rec>2) return false;
  50. if (indegree[i]==outdegree[i]+1) flag1=1;
  51. else if (indegree[i]==outdegree[i]-1) flag2=1;
  52. else return false;
  53. }
  54. }
  55. if (count_!=1) return false;
  56. if (rec==0 || (rec==2 && flag1&flag2)) return true;
  57. else return false;
  58. return true;
  59. }
  60. int main()
  61. {
  62. int u,v,t,j;
  63. int first,last;
  64. char word[1005];
  65. scanf("%d",&t);
  66. while(t--)
  67. {
  68. scanf("%d",&n);
  69. count_=0;
  70. memset(indegree,0,sizeof(indegree));
  71. memset(outdegree,0,sizeof(outdegree));
  72. memset(hash_,true,sizeof(hash_));
  73. init();
  74. for (int i=0; i<n; i++)
  75. {
  76. scanf("%s",word);
  77. first=word[0]-97;
  78. for(j=0;word[j]!='\0';j++);
  79. last=word[j-1]-97;
  80. outdegree[first]++;
  81. indegree[last]++;
  82. if (hash_[first])
  83. {
  84. hash_[first]=false;
  85. count_++;
  86. }
  87. if (hash_[last])
  88. {
  89. hash_[last]=false;
  90. count_++;
  91. }
  92. unite(first,last);
  93. }
  94. if (judge()) printf("Ordering is possible.\n");
  95. else printf("The door cannot be opened.\n");
  96. }
  97. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注