• c++香甜的黄油(acwing)


    农夫John发现了做出全威斯康辛州最甜的黄油的方法:糖。

    把糖放在一片牧场上,他知道 N 只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。

    当然,他将付出额外的费用在奶牛上。

    农夫John很狡猾,就像以前的巴甫洛夫,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。

    他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。

    农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。

    给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)。

    数据保证至少存在一个牧场和所有牛所在的牧场连通

    输入格式

    第一行: 三个数:奶牛数 N,牧场数 P,牧场间道路数 C。

    第二行到第 N+1 行: 1 到 N 头奶牛所在的牧场号。

    第 N+2 行到第 N+C+1 行:每行有三个数:相连的牧场A、B,两牧场间距 D,当然,连接是双向的

    输出格式

    共一行,输出奶牛必须行走的最小的距离和。

    数据范围

    1≤N≤500,
    2≤P≤800,
    1≤C≤1450,
    1≤D≤255

    输入样例:
    1. 3 4 5
    2. 2
    3. 3
    4. 4
    5. 1 2 1
    6. 1 3 5
    7. 2 3 7
    8. 2 4 3
    9. 3 4 5

    输出样例:

    8

    代码如下

    dijkstra和spfa两个代码AC时间

    第一个是spfa,第二个是dijkstra,但是我还是更喜欢dijkstra(heihei)

    spfa

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. typedef pair<int, int> PII;
    7. const int N = 810, M = 3000, INF = 0x3f3f3f3f;
    8. int n, p, m;//n是奶牛数量,p是牧场数量,m是道路数量
    9. int h[N], w[M], e[M], ne[M], idx;
    10. int dist[N], cnt[N];//cnt记录编号
    11. bool st[N];
    12. void add(int a, int b, int c)
    13. {
    14. e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
    15. }
    16. int spfa(int u)
    17. {
    18. memset(dist, 0x3f, sizeof dist);
    19. //memset(st, 0, sizeof st);//这里不需要每次清空st数组
    20. queue<int> q;
    21. dist[u] = 0;
    22. q.push(u);
    23. st[u] = true;
    24. while(q.size())
    25. {
    26. auto t = q.front();
    27. q.pop();
    28. st[t] = false;
    29. for(int i = h[t]; ~i; i = ne[i])
    30. {
    31. int j = e[i];
    32. if(dist[j] > dist[t] + w[i])
    33. {
    34. dist[j] = dist[t] + w[i];
    35. if(!st[j])
    36. {
    37. st[j] = true;
    38. q.push(j);
    39. }
    40. }
    41. }
    42. }
    43. int res = 0;
    44. for(int i = 0; i < n; i ++)
    45. {
    46. int j = cnt[i];
    47. if(dist[j] == INF) return INF;
    48. res += dist[j];把每次求的结果相加起来
    49. }
    50. return res;
    51. }
    52. int main()
    53. {
    54. cin >> n >> p >> m;
    55. memset(h, -1, sizeof h);
    56. for(int i = 0; i < n; i ++) cin >> cnt[i];
    57. while(m --)
    58. {
    59. int a, b, c;
    60. scanf("%d%d%d", &a, &b, &c);
    61. add(a, b, c), add(b, a, c);
    62. }
    63. int t = INF;
    64. for(int i = 1; i <= p; i ++)
    65. {
    66. t = min(t, spfa(i));//求最小距离
    67. }
    68. cout << t << endl;
    69. return 0;
    70. }

    1、注意输入,总是输入出错误,哭死,因为每片牧场不只有一头牛,所以cnt数组记录牛的编号

    然后注意道路是m,因为是求到牧场之间的距离和,所以是1到p

    2、每次跑完最短路之后把每次的距离和相加起来

    3、剩下的就是模板

    dijkstra

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. typedef pair<int, int> PII;
    7. const int N = 810, M = 3000, INF = 0x3f3f3f3f;
    8. int n, p, m;
    9. int h[N], w[M], e[M], ne[M], idx;
    10. int dist[N], cnt[N];
    11. bool st[N];
    12. void add(int a, int b, int c)
    13. {
    14. e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
    15. }
    16. int dijkstra(int u)
    17. {
    18. memset(st, 0, sizeof st);
    19. memset(dist, 0x3f, sizeof dist);
    20. priority_queue, greater> heap;
    21. heap.push({0, u});
    22. dist[u] = 0;
    23. while(heap.size())
    24. {
    25. auto t = heap.top();
    26. heap.pop();
    27. int ver = t.second, distance = t.first;
    28. if(st[ver]) continue;
    29. st[ver] = true;
    30. for(int i = h[ver]; i != -1; i = ne[i])
    31. {
    32. int j = e[i];
    33. if(dist[j] > dist[ver] + w[i])
    34. {
    35. dist[j] = dist[ver] + w[i];
    36. heap.push({dist[j], j});
    37. }
    38. }
    39. }
    40. int res = 0;
    41. for(int i = 0; i < n; i ++)
    42. {
    43. int j = cnt[i];
    44. if(dist[j] == INF) return INF;
    45. res += dist[j];
    46. }
    47. return res;
    48. }
    49. int main()
    50. {
    51. cin >> n >> p >> m;
    52. memset(h, -1, sizeof h);
    53. for(int i = 0; i < n; i ++) cin >> cnt[i];
    54. while(m --)
    55. {
    56. int a, b, c;
    57. scanf("%d%d%d", &a, &b, &c);
    58. add(a, b, c), add(b, a, c);
    59. }
    60. int t = INF;
    61. for(int i = 1; i <= p; i ++)
    62. {
    63. t = min(t, dijkstra(i));
    64. }
    65. cout << t << endl;
    66. return 0;
    67. }

    1、其实代码都相差不多,就是注意dijkstra每次都要清空st数组

    2、希望小伙伴两种算法都能熟练地背下来,一个处理正权,一个处理友负权边的问题

  • 相关阅读:
    python的多线程使用
    数据结构题目收录(四)
    muduo库的高性能日志库(四)——LogFile文件
    放弃5k事业编选择了15k的程序员,真的值得么?
    单片机第二季:温度传感器DS18B20
    多线程之线程池
    LC-396. 旋转函数(前缀和+滑动窗口、动态规划)
    c++实现多重继承
    Python3 字典
    第 1 章 微信小程序与云开发从入门到实践从零开始做小程序——开发认识微信小程序
  • 原文地址:https://blog.csdn.net/2301_76180325/article/details/133858261