• [最短路]猛犸不上 Ban 2021RoboCom决赛D


    在一个名叫刀塔的国家里,有一只猛犸正在到处跑着,希望能够用它的长角抛物技能来撞飞别人。已知刀塔国有 N 座城市,城市之间由 M 条道路互相连接,为了拦住这头猛犸,每条道路上设置了 Vi​ 人的团队。

    这只猛犸从 S 号城市出发,它可以选择:

    1. 在不重复地经过若干条道路后回到 S 号城市;
    2. 在不重复地经过若干条道路后到达 T 号城市。

    猛犸经过一条道路后,就会把路上的人全部撞飞。作为一头爱喝雪碧的仁慈的猛犸,自然希望尽可能的少撞飞人。请你帮忙计算一下在最优的选择下,最少需要撞飞多少人才能够到达目标城市?

    输入格式:

    输入第一行是四个正整数 N,M,S,T (2≤N≤500,1≤M≤105),表示有 N 个城市,M 条道路,猛犸从 S 号城市出发,可以选择到达 T 号城市。

    接下来的 M 行,每行三个正整数 Xi​,Yi​,Vi​ (0≤Vi​≤100),表示从 Xi​ 号城市到 Yi​ 号城市有一条道路,道路上有 Vi​ 人的团队。道路可双向通行,城市编号从 1 开始,两个城市之间最多只有一条道路,且没有一条道路连接相同的城市。

    数据保证两种选择里至少有一种是可行的。

    输出格式:

    输出两行,第一行是两个数字,分别对应上面的两种选择分别最少需要撞飞多少人。如果无论撞飞多少人都无法满足选择要求,则输出 -1

    第二行是一个句子,如果第一种(回到原点)的选择比较好,就输出 Win!,否则输出Lose!

    输入样例:

    1. 5 6 1 5
    2. 1 2 1
    3. 2 3 2
    4. 3 4 3
    5. 4 1 5
    6. 3 5 4
    7. 4 5 1

    输出样例:

    在这里给出相应的输出。例如:

    1. 11 6
    2. Lose!

    题意: 有n个点m条边,起点s和终点t,现在猛犸有两种行动路径,一种是从s走到t,一种是从s出发转一圈再回到s,两种行动都不允许重复经过同一条边,问各自最短路是多少。

    分析: 对于从s到t的最短路很简单,就是套一个dijkstra板子,对于从s出去再绕一圈回来的情况,其实就相当于从s的某个相邻节点i出发,并且删掉i到s的那条边的情况下从i走到s的最短路,再加上i到s的边权就是这一圈下来从i出发的最短路了,猛犸可能从s的各个相邻点出发,所以需要每个相邻点都处理一遍,也就是跑最多n-1次dijkstra,取一个最小值就是绕圈下的最短路了,时间复杂度为O(n*m*logn),如果不使用堆优化的dijkstra可能会更快。

    具体代码如下:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define inf 0x3f3f3f3f
    10. #define pii pair
    11. using namespace std;
    12. int n, m, s, t, mn;
    13. vector g[505];
    14. bool vis[505];
    15. int dis[505];
    16. void dijkstra(int s, int type){
    17. priority_queue, greater >q;
    18. dis[s] = 0;
    19. q.push(make_pair(dis[s], s));
    20. while(q.size()){
    21. int now = q.top().second;
    22. q.pop();
    23. if(vis[now]) continue;
    24. vis[now] = true;
    25. for(int i = 0; i < g[now].size(); i++){
    26. int to = g[now][i].second, w = g[now][i].first;
    27. if(type == 1 && now == s && to == ::s) continue;//禁用某条边
    28. if(dis[to] > dis[now]+w){
    29. dis[to] = dis[now]+w;
    30. q.push(make_pair(dis[to], to));
    31. }
    32. }
    33. }
    34. }
    35. signed main()
    36. {
    37. ios::sync_with_stdio(0);
    38. cin.tie(0);
    39. cin >> n >> m >> s >> t;
    40. for(int i = 1; i <= n; i++){
    41. dis[i] = inf;
    42. vis[i] = false;
    43. }
    44. for(int i = 1; i <= m; i++){
    45. int u, v, w;
    46. cin >> u >> v >> w;
    47. g[u].push_back(make_pair(w, v));
    48. g[v].push_back(make_pair(w, u));
    49. }
    50. dijkstra(s, 0);
    51. int temp = dis[t];
    52. int mn = inf;
    53. for(int i = 0; i < g[s].size(); i++){
    54. int to = g[s][i].second, w = g[s][i].first;
    55. for(int j = 1; j <= n; j++){
    56. vis[j] = false;
    57. dis[j] = inf;
    58. }
    59. dijkstra(to, 1);
    60. mn = min(mn, dis[s]+w);
    61. }
    62. if(mn != inf) cout << mn << " ";
    63. else cout << "-1 ";
    64. if(temp != inf) cout << temp;
    65. else cout << "-1";
    66. cout << endl;
    67. if(mn < temp) cout << "Win!";
    68. else cout << "Lose!";
    69. return 0;
    70. }

  • 相关阅读:
    免疫检查点 PD-1 与中枢神经系统(CNS)的生理学关系 | MedChemExpress
    实时流处理与分布式存储过程中对文件的操作
    Linux内存查看通用方法
    【21t天算法挑战赛】排序算法——直接选择排序
    让写代码燃起来!vscode插件Power Mode
    byte数据与Int和bit转换类
    机器学习-计算数据之间的距离
    POI2020题解
    Apache Doris tablet 副本修复的原理、流程及问题定位
    小笔记:02-jquery-将url作为参数传递给后端,需要进行的特殊处理
  • 原文地址:https://blog.csdn.net/m0_55982600/article/details/126215807