zoukankan      html  css  js  c++  java
  • URAL 1934 最短路变形

    DES:给出起点和终点。给出所有小岛的编号。所有路径的起始点。和遇到怪物的概率。要求在最短路的条件下维护遇见怪物的概率最小的路径。就是用 SPFA算法。每条路的权值设为1。最短路即为途径的岛数最少。同时要用pre数组维护每个点的前驱。最后递归输出所走路径。把p变为不遇见怪物的概率, 即为维护p最大。就是把原来的SPFA里的判断多加一条,如果权值相等判断概率,选择概率大的一条。

    注意。这是无向图。本来觉得没有影响。很幸福的WA了。确实是。给你a->b的,就代表可以从b->a。而不是简单的可以往返。

    不知道用邻接表和邻接矩阵时间差大不大。这里用了邻接表

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    using namespace std;
    #include<queue>
    #define N 100010
    #define inf 0x1f1f1f1f
    
    int low[N]; //存储源点到每个顶点的最短距离值
    bool in_que[N]; //标记一个点是否已在队列中
    int cnt[N]; //记录每个点的入队次数,来判断是否出现负环
    int pre[N]; // 记录每个点的前驱。即记录源点到每个点的最短路径本身。
    int head[N]; //邻接矩阵的表头节点
    double p[N]; //存储最短路的情况下。到每个点的p最大。
    int n, m;
    int h;
    bool flag = true;
    
    struct Edge
    {
        int v, w, next;
        double p;
    }edge[N<<1];
    
    void addEdge(int a, int b, double c)
    {
         edge[h].v = b;
         edge[h].w = 1;
         edge[h].p = c;
         edge[h].next = head[a];
         head[a] = h++;
    }
    
    void spfa(int s)
    {
         for (int i=0; i<=n; ++i)
         {
             p[i] = 0;
             low[i] = inf;
         }
         memset(pre, -1, sizeof(pre));
         memset(in_que, 0, sizeof(in_que));
         queue<int>q;
         in_que[s] = 1;
         low[s] = 1;
         p[s] = 1; //没有怪物
         q.push(s);
    
         while(!q.empty())
         {
             int x = q.front();
             q.pop();
             in_que[x] = 0;
             for (int i=head[x]; i!=-1; i=edge[i].next)
             {
                 int v = edge[i].v;
                 if (low[v] > low[x]+1)
                 {
                    low[v] = low[x] + 1;
                    p[v] = p[x]*edge[i].p;
                    pre[v] = x;
                    if (!in_que[v])
                    {
                        in_que[v] = 1;
                        q.push(v);
                    }
                 }
                 else if (low[v] == low[x] + 1)
                 {
                     if (p[v] < p[x]*edge[i].p)
                     {
                         p[v] = p[x]*edge[i].p;
                         pre[v] = x;
                         if (!in_que[v])
                         {
                             in_que[v] = 1;
                             q.push(v);
                         }
                     }
                 }
             }
         }
         return;
    }
    
    void output(int r)
    {
        if (pre[r] != -1) output(pre[r]);
        if (flag) flag = false;
        else putchar(' ');
        printf("%d", r);
    }
    
    int main()
    {
        int s, t;
        int a, b;
        double c;
        while(~scanf("%d%d", &n, &m))
        {
            scanf("%d%d", &s, &t);
            h = 0;
            memset(head, -1, sizeof(head));
            for (int i=0; i<m; ++i)
            {
                scanf("%d%d%lf", &a, &b, &c);
                c = (1-c/100);
                addEdge(a, b, c);
                addEdge(b, a, c);
            }
            spfa(s);
            printf("%d %.6lf
    ", low[t], 1-p[t]);
            flag = true;
            output(t);
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    部分网络加载预训练模型代码实现
    数据不平衡处理方法
    面试题目汇总
    多线程和多进程
    数据结构知识点总结
    GBDT和XGBoost的区别
    GBDT和随机森林的区别
    机器学习-特征处理
    一篇写得很好的关于lct的博客
    Count and Say 2014/10/23
  • 原文地址:https://www.cnblogs.com/icode-girl/p/4685382.html
Copyright © 2011-2022 走看看