HDU3499Flight(双向Dijkstra)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3499

题意:

        有一个有向图,你要从特定的城市A飞到城市B去.给你这个图的所有边(航班)信息.但是你手上有一张卡,可以使得某一趟航班的价格减半.现在的问题是你从A到B的最小费用是多少?

分析:

        首先要知道这条如果让一条原本是最短路径(假设总距离为x)上最长的边变成半价,最终求得的解不一定是最优的。因为假如现在有另外一条路径,假设该路径距离为x+1。且这条路径上只有5条边,4条长为1的边,但是1条长为x-3的边。如果我们让这条路径的x-3边变成半价是不是能得到更好的结果?

        明显必须从m条边中枚举那条半价的航班.假设这条半价的航班是i->j的.那么我们必须知道从A到i的最短距离和从j到B的最短距离. 从A到i的最短距离可以通过求A的单源最短路径即可.从j(j有可能是任意点)到B的最短距离必须建立原图的反向图,然后求B到其他所有点的单源最短路径.(想想是不是)

        原题输入数据很多,需要用邻接表的dijkstra算法且距离要用long long保存


结构体封装代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
const long long INF = 1e17;
const int maxn = 100005;
const int maxm = 500005;
int n, m;
map<string, int> mp;
struct Edge
{
    int form, to, next;
    long long dist;
    Edge(){}
    Edge(int _form, int _to, long long _dist):form(_form), to(_to), dist(_dist){}
    Edge(int _form, int _to, long long _dist, int _next):form(_form), to(_to), dist(_dist), next(_next){}
}edge[maxm];
struct HeapNode
{
    long long d;
    int u;
    HeapNode(){}
    HeapNode(int _u, long long _d):u(_u), d(_d){};
    bool operator < (const HeapNode &other) const
    {
        return d > other.d;
    }
};
struct Dijkstra
{
    int n, m, head[maxm];
    Edge edge[maxm];
    long long dis[maxn];
    void init()
    {
        m = 0;
        memset(head, -1, sizeof(head));
    }
    void add_edge(int from, int to, long long dist)
    {
        edge[m] = Edge(from, to, dist, head[from]);
        head[from] = m++;
    }
    void dijkstra(int s)
    {
        priority_queue<HeapNode> q;
        for(int i = 0; i < n; i++)
            dis[i] = i == s ? 0 : INF;
        q.push(HeapNode(s, dis[s]));
        while(!q.empty())
        {
            HeapNode x = q.top();
            q.pop();
            int u = x.u;
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                if(dis[edge[i].to] > dis[u] + edge[i].dist)
                {
                    dis[edge[i].to] = dis[u] + edge[i].dist;
                    q.push(HeapNode(edge[i].to, dis[edge[i].to]));
                }
            }
        }
    }
}dj1, dj2;
int getid(string s)
{
    if(mp.find(s) == mp.end())
        mp[s] = n++;
    return mp[s];
}
int main()
{
    int u, v;
    long long w;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        n = 0;
        mp.clear();
        string s1, s2;
        dj1.init();dj2.init();
        for(int i = 0; i < m ; i++)
        {
            cin >> s1 >> s2 >> w;
            u = getid(s1);
            v = getid(s2);
            dj1.add_edge(u, v, w);
            dj2.add_edge(v, u, w);
            edge[i] = Edge(u, v, w);
        }
        cin >> s1 >> s2;
        int st = getid(s1), ed = getid(s2);
        dj1.n = dj2.n = n;
        dj1.dijkstra(st), dj2.dijkstra(ed);
        if(dj1.dis[ed] == INF)
        {
            printf("-1\n");
            continue;
        }
        long long ans = INF;
        for(int i = 0; i < m; i++)
        {
            int u  = edge[i].form, v = edge[i].to;
            long long w  = edge[i].dist;
            if(ans >  dj1.dis[u] + dj2.dis[v] + w / 2)
                ans =  dj1.dis[u] + dj2.dis[v] + w / 2;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

二维数组代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
const int maxm = 500005;
const int maxn = 100005;
const long long INF = 1e17;
struct Edge
{
    int u, v, next;
    long long w;
    Edge(){}
    Edge(int _u, int _v, long long _w, int _next):u(_u), v(_v), w(_w), next(_next){}
}edge[2][maxm];
struct HeapNode
{
    long long d;
    int u;
    HeapNode(int _u, long long _d):u(_u), d(_d){}
    bool operator < (const HeapNode &other)const
    {
        return d > other.d;
    }
};
int n, m, head[2][maxn];
long long dis[2][maxn];
map<string, int> mp;
int getid(string s)
{
    if(mp.find(s) == mp.end())
        mp[s] = n++;
    return mp[s];
}
void Dijkstra(int flag, int s)
{
    for(int i = 0; i < n; i++)
        dis[flag][i] = INF;
    dis[flag][s] = 0;
    priority_queue<HeapNode> q;
    q.push(HeapNode(s, dis[flag][s]));
    while(!q.empty())
    {
        HeapNode now = q.top();
        q.pop();
        for(int i = head[flag][now.u]; i != -1; i = edge[flag][i].next)
        {
            int to = edge[flag][i].v;
            if(dis[flag][to] > dis[flag][now.u] + edge[flag][i].w)
            {
                dis[flag][to] = dis[flag][now.u] + edge[flag][i].w;
                q.push(HeapNode(to, dis[flag][to]));
            }
        }
    }
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        n = 0;
        string s1, s2;
        mp.clear();
        memset(head, -1, sizeof(head));
        memset(dis, 63, sizeof(dis));
        for(int i = 0; i < m; i++)
        {
            long long w;
            cin >> s1 >> s2 >> w;
            int u = getid(s1), v = getid(s2);
            edge[0][i] = Edge(u, v, w, head[0][u]);
            head[0][u] = i;
            edge[1][i] = Edge(v, u, w, head[1][v]);
            head[1][v] = i;
        }
        cin >> s1 >> s2;
        int st = getid(s1), ed = getid(s2);
        Dijkstra(0, st);
        Dijkstra(1, ed);
        if(dis[0][ed] == INF)
        {
            printf("-1\n");
            continue;
        }
        long long ans = INF;
        for(int i = 0; i < m; i++)
        {
            int u = edge[0][i].u, v = edge[0][i].v;
            long long dist = edge[0][i].w;
            if(ans > dis[0][u] + dis[1][v] + dist / 2)
                ans = dis[0][u] + dis[1][v] + dist / 2;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值