[关闭]
@yuyuesheng 2019-01-29T01:26:41.000000Z 字数 2210 阅读 798

D - 欧拉路

题意:判断一个无向图是否是欧拉回路
题解:
无向图存在欧拉回路的充要条件:
一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图
所以先用并查集判断图的连通性,在统计各点的度。

  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. const int maxn = 1e3 + 500;
  5. int fa[maxn], r[maxn];
  6. int n, m, s, t, cnt[maxn];
  7. void init() {
  8. for (int i = 1; i <= n; i++) {
  9. fa[i] = i;
  10. r[i] = 1;
  11. }
  12. }
  13. int Find(int x) {
  14. while (x != fa[x]) {
  15. x = fa[x];
  16. }
  17. return x;
  18. }
  19. void Union(int x, int y) {
  20. int fx = Find(x), fy = Find(y);
  21. if (fx == fy) return;
  22. if (r[fx] < r[fy]) {
  23. fa[fx] = fy;
  24. }
  25. else {
  26. fa[fy] = fx;
  27. if (r[fx] == r[fy]) r[fx]++;
  28. }
  29. }
  30. int main()
  31. {
  32. while (cin >> n) {
  33. if (n == 0)
  34. break;
  35. cin >> m;
  36. init();
  37. memset(cnt, 0, sizeof(cnt));
  38. for (int i = 0; i < m; i++)
  39. {
  40. cin >> s >> t;
  41. Union(s, t);
  42. cnt[s]++;
  43. cnt[t] ++;
  44. }
  45. int k = 0;
  46. for (int i = 1; i <= n; i++)
  47. {
  48. if (Find(i) != Find(1))
  49. k = 1;
  50. if (cnt[i] % 2 != 0)
  51. k = 1;
  52. }
  53. if (k)
  54. cout << 0 << endl;
  55. else
  56. cout << 1 << endl;
  57. }
  58. }

E - 拓扑排序

题意:对一个有向图进行拓扑排序
题解:
循环执行以下两步,直到不存在入度为0的顶点为止。
(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有出边。
比较坑的是题目中可能会存在同一条边重复输入的问题。

  1. #include<iostream>
  2. #include<queue>
  3. #include<cstring>
  4. using namespace std;
  5. const int maxn = 550;
  6. bool e[maxn][maxn];
  7. int in[maxn],n,m,s,t;
  8. priority_queue<int, vector<int>, greater<int> > q;
  9. void ans()
  10. {
  11. for (int i = 1; i <= n; i++)
  12. {
  13. if (in[i] == 0)
  14. q.push(i);
  15. }
  16. int cnt = 1;
  17. while (!q.empty())
  18. {
  19. int s = q.top();
  20. q.pop();
  21. if (cnt != n)
  22. {
  23. cout << s << " ";
  24. cnt++;
  25. }
  26. else
  27. cout << s << endl;
  28. for (int i = 1; i <= n; i++)
  29. {
  30. if (!e[s][i])
  31. continue;
  32. in[i]--;
  33. if (!in[i])
  34. q.push(i);
  35. }
  36. }
  37. }
  38. int main()
  39. {
  40. while (cin >> n >> m)
  41. {
  42. memset(e, 0, sizeof(e));
  43. memset(in, 0, sizeof(in));
  44. while (m--)
  45. {
  46. cin >> s >> t;
  47. if (e[s][t] == 0) {
  48. e[s][t] = 1;
  49. in[t]++;
  50. }
  51. }
  52. ans();
  53. }
  54. }

F - 拓扑排序

题意:年终要给 n 个员工发奖金,每个人的起始金额是888,有些人觉得自己做的比另一个人好所以应该多得一些钱,问最少需要花多少钱,如果不能满足所有员工的要求,输出 -1。
题解:进行拓扑排序,依照入度情况对888进行加法操作。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<queue>
  4. #include<vector>
  5. using namespace std;
  6. const int maxn = 10050;
  7. vector<int>e[maxn];
  8. int ans[maxn];
  9. int in[maxn];
  10. queue<int> q;
  11. int n, m;
  12. void solve()
  13. {
  14. for (int i = 1; i <= n; i++)
  15. {
  16. if (in[i] == 0)
  17. {
  18. q.push(i);
  19. ans[i] = 888;
  20. in[i]--;
  21. }
  22. }
  23. while (!q.empty())
  24. {
  25. int s = q.front();
  26. q.pop();
  27. for (int i = 0; i < e[s].size(); i++)
  28. {
  29. in[e[s][i]]--;
  30. if (in[e[s][i]] == 0)
  31. {
  32. q.push(e[s][i]);
  33. ans[e[s][i]] = ans[s] + 1;
  34. in[e[s][i]]--;
  35. }
  36. }
  37. }
  38. int flag = 0;
  39. int cnt = 0;
  40. for (int i = 1; i <= n; i++)
  41. {
  42. if (in[i] != -1)
  43. flag++; //说明存在回路,无法确定
  44. }
  45. if (flag != 0)
  46. cout << -1 << endl;
  47. else
  48. {
  49. for (int i = 1; i <= n; i++)
  50. cnt += ans[i];
  51. cout << cnt << endl;
  52. }
  53. }
  54. int main()
  55. {
  56. while (cin>>n>>m)
  57. {
  58. for (int i = 0; i <= n; i++)
  59. e[i].clear();
  60. while (!q.empty())
  61. q.pop();
  62. memset(in, 0, sizeof(in));
  63. memset(ans, 0, sizeof(ans));
  64. for (int i = 0; i < m; i++)
  65. {
  66. int s, t;
  67. cin >> t >> s;
  68. in[t]++;
  69. e[s].push_back(t);
  70. }
  71. solve();
  72. }
  73. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注