StkOvflow

STACK OVERFLOW!

一言(ヒトコト)

这年头 expert 很难么?
——zn

AcWing1137. 选择最佳线路

题目传送门

题目大意

有一张有向图,可以有若干个起点,只有一个终点,求所有起点到终点的最短路中最短的一条,若所有起点都与终点不连通,则输出1

解题思路

我们这题可以想出两个方面的思路:
1.我们可以设置虚拟源点S=0(),连接S与所有的起点,边权都为0,跑S到终点的最短路,这样最后得到的最短路就是题目所求
2.我们可以反向建图,然后跑从终点为源点的最短路,然后枚举所有起点,用全局变量res记录全局最小值。

为什么可以

因为虚拟源点S到所有起点的边权都为0,所以从S开始不会改变最短路的长度,又因为它同时确保了原先作为起点的每个点都是可以出现在路径中的,所以我们用S做源点跑出来的最短路,就是所有起点到终点的最短路的最短的一条
此处,反向建图不做解释。

代码实现

这里提供四份代码
分别是
1.Dijkstra
2.SPFA
3.Dijkstra
4.SPFA
提醒:别忘记了初始化idx,清空邻接表和标记数组!!!

Dijkstra
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;

const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn;

void add(int a, int b, int c) 
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

void Dijkstra(int S) 
{
    memset(st, 0, sizeof st);
    memset(dist, 0x3f, sizeof dist);
    priority_queue<PII, vector<PII>, greater<> > heap;
    dist[S] = 0, heap.push({0, S});
    
    while (heap.size()) 
    {
        auto t = heap.top().second; heap.pop();
        
        if (st[t]) continue ;
        st[t] = true ; 
        
        for (int i = h[t]; ~i; i = ne[i]) 
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i]) 
            {
                dist[j] = dist[t] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
}

int main() 
{
    while (~scanf("%d%d%d", &n, &m, &T))
    {
        vector<int> stops; idx = 0;
        
        memset(h, -1, sizeof h);
        
        while (m -- )
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w); //反向建图
        }
        
        int S = 0;
        scanf("%d", &stn);
        while (stn -- ) 
        {
            int x;
            scanf("%d", &x);
            add(S, x, 0);
        }
        
        Dijkstra(S);
        
        int res = dist[T];
        if (res == INF) puts("-1");
        else printf("%d\n", res);
    }
    
    return 0;
}
2.SPFA
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;

const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn;

void add(int a, int b, int c) 
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

void spfa(int S) 
{
    memset(st, 0, sizeof st);
    memset(dist, 0x3f, sizeof dist);
    queue<int> q;
    
    dist[S] = 0, st[S] = true, q.push(S);
    
    while (q.size()) 
    {
        auto t = q.front(); q.pop();
        st[t] = false ;
        
        for (int i = h[t]; ~i; i = ne[i]) 
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i]) 
            {
                dist[j] = dist[t] + w[i];
                if (!st[j]) st[j] = true, q.push(j);
            }
        }
    }
}

int main() 
{
    while (~scanf("%d%d%d", &n, &m, &T))
    {
        vector<int> stops; idx = 0;
        
        memset(h, -1, sizeof h);
        
        while (m -- )
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w); //反向建图
        }
        
        int S = 0;
        scanf("%d", &stn);
        while (stn -- ) 
        {
            int x;
            scanf("%d", &x);
            add(S, x, 0);
        }
        
        spfa(S);
        
        int res = dist[T];
        if (res == INF) puts("-1");
        else printf("%d\n", res);
    }
    
    return 0;
}
3.Dijkstra
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;

const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn;

void add(int a, int b, int c) 
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

void Dijkstra(int S) 
{
    memset(st, 0, sizeof st);
    memset(dist, 0x3f, sizeof dist);
    priority_queue<PII, vector<PII>, greater<> > heap;
    dist[S] = 0, heap.push({0, S});
    
    while (heap.size()) 
    {
        auto t = heap.top().second; heap.pop();
        
        if (st[t]) continue ;
        st[t] = true ; 
        
        for (int i = h[t]; ~i; i = ne[i]) 
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i]) 
            {
                dist[j] = dist[t] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
}

int main() 
{
    while (~scanf("%d%d%d", &n, &m, &T))
    {
        vector<int> stops; idx = 0;
        
        memset(h, -1, sizeof h);
        
        while (m -- )
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(v, u, w); //反向建图
        }
        scanf("%d", &stn);
        while (stn -- ) 
        {
            int x;
            scanf("%d", &x);
            stops.push_back(x);
        }
        
        Dijkstra(T);
        
        int res = INF;
        for (auto i : stops) res = min(res, dist[i]);
        if (res == INF) printf("%d\n", -1);
        else printf("%d\n", res);
    }
    
    return 0;
}
4.SPFA
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;

const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn;

void add(int a, int b, int c) 
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

void spfa(int S) 
{
    memset(st, 0, sizeof st);
    memset(dist, 0x3f, sizeof dist);
    queue<int> q;
    
    q.push(S), dist[S] = 0, st[S] = true ;
    
    while (q.size()) 
    {
        auto t = q.front(); q.pop();
        st[t] = false ; 
        
        for (int i = h[t]; ~i; i = ne[i]) 
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i]) 
            {
                dist[j] = dist[t] + w[i];
                if (!st[j]) q.push(j), st[j] = true ;
            }
        }
    }
}

int main() 
{
    while (~scanf("%d%d%d", &n, &m, &T))
    {
        vector<int> stops; idx = 0;
        
        memset(h, -1, sizeof h);
        
        while (m -- )
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w); //反向建图
        }
        
        int S = 0;
        scanf("%d", &stn);
        while (stn -- ) 
        {
            int x;
            scanf("%d", &x);
            add(S, x, 0);
        }
        
        spfa(S);
        
        int res = dist[T];
        if (res == INF) puts("-1");
        else printf("%d\n", res);
    }
    
    return 0;
}

Accepted!

posted @   StkOvflow  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示