1126. 最小花费

毒瘤题。。。卡了好久

本题求乘积最大的路径,咋一看好像是最长路直接无脑跑\(spfa\),事实上\(spfa\)的确能跑过。

但本题也可以用\(dijkstra\)求解,原因是边权有特殊的性质:\(0<w<1\)

这就导致了如果\(s->...->t->...>e\)\(s\)\(e\)乘积最大的路径,那么\(s->...->t\)也是\(s\)\(t\)乘积最大的路径,即满足最优子结构性质。

因此\(dijkstra\)算法每次取权值最大的边相乘即可。

至于\(s->...->t\)为什么一定是最大的,而不会走其他边绕路被更新。

  • 因为\(0<w<1\),走其他边绕路必然会越乘越小,必然不会更新
const int N=2010;
vector<PID> g[N];
double dist[N];
bool vis[N];
int n,m,s,e;

void dijkstra()
{
    priority_queue<PDI> heap;
    heap.push({0,s});
    dist[s]=1;

    while(heap.size())
    {
        int t=heap.top().second;
        heap.pop();

        if(vis[t]) continue;
        vis[t]=true;

        for(int i=0;i<g[t].size();i++)
        {
            int j=g[t][i].fi;
            double w=g[t][i].se;
            if(dist[j] < dist[t]*w)
            {
                dist[j]=dist[t]*w;
                heap.push({dist[j],j});
            }
        }
    }
}

int main()
{
    cin>>n>>m;

    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a].pb({b,(100-c)/100.0});
        g[b].pb({a,(100-c)/100.0});
    }

    cin>>s>>e;

    dijkstra();

    printf("%.8f\n",100/dist[e]);
    //system("pause");
}
posted @ 2020-09-26 11:13  Dazzling!  阅读(109)  评论(0编辑  收藏  举报