POJ 4046 Sightseeing

最短路的变形,因为要加上最大的点权,所以只能枚举以每一个点为起始点且为最大点权的最短路。

则对于每次询问有 Min = min(Min,dis[i][s] + dis[i][t] + val[i])。

然后此题需要好多细节上的优化。

比如,能用全局就用全局。

然后又重新搞了一遍SPFA。。。。竟然不会写了。。。。

以前写最短路一直在用bfs +  priority_queue,不过竟然比spfa慢。。。


-------------------------updata------------------------------

其实bfs + priority_queue还是蛮可以的 . . . .一定是上次写挫了。。。。最后面附上bfs+priority_queue的代码。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 1e18
#define Mod 6000007

using namespace std;

LL val[1010];

struct N
{
    LL w;
    int v,next;
}edge[40010];

int head[1010];

int Top;

void Link(int u,int v,LL w)
{
    edge[Top].v = v;
    edge[Top].w = w;
    edge[Top].next = head[u];
    head[u] = Top++;
}

LL dis[1010];

bool mark[1010];
queue<int> q;
void Cal(int s,int n)
{
    memset(mark,false,sizeof(bool)*(n+2));
    int f,t;

    for(int i = 1;i <= n; ++i)
        dis[i] = INF;

    f = s;

    dis[s] = 0;

    q.push(f);
    mark[s] = true;

    while(q.empty() == false)
    {
        f = q.front();
        q.pop();

        mark[f] = false;

        for(int p = head[f];p != -1; p = edge[p].next)
        {
            if(val[edge[p].v] > val[s])
                continue;

            if(dis[f] + edge[p].w < dis[edge[p].v])
            {
                dis[edge[p].v] = dis[f] + edge[p].w;

                if(mark[edge[p].v] == false)
                {
                   mark[edge[p].v] = true;
                   t = edge[p].v;
                   q.push(t);
                }
            }
        }
    }
}

int S[20010],T[20010];

LL Min[20010];

int main()
{
    int n,m,i,j,u,v;
    LL w;

    while(scanf("%d %d",&n,&m) && (n||m))
    {
        memset(head,-1,sizeof(int)*(n+2));
        Top = 0;

        for(i = 1;i <= n; ++i)
        {
            scanf("%lld",&val[i]);
        }
        for(i = 1;i <= m; ++i)
        {
            scanf("%d %d %lld",&u,&v,&w);
            Link(u,v,w);
            Link(v,u,w);
        }

        scanf("%d",&m);

        for(i = 0;i < m; ++i)
        {
            scanf("%d %d",&S[i],&T[i]);
            Min[i] = INF;
        }

        for(i = 1;i <= n; ++i)
        {
            Cal(i,n);
            for(w = 0;w < m; ++w)
            {
                Min[w] = min(Min[w],dis[S[w]] + dis[T[w]] + val[i]);
            }
        }

        for(i = 0;i < m; ++i)
        {
            if(Min[i] == INF)
                printf("-1\n");
            else
                printf("%lld\n",Min[i]);
        }

        printf("\n");
    }

    return 0;
}


bfs+priority_queue


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 1e18
#define Mod 6000007

using namespace std;

LL val[1010];

struct N
{
    LL w;
    int v,next;
}edge[40010];

int head[1010];

int Top;

void Link(int u,int v,LL w)
{
    edge[Top].v = v;
    edge[Top].w = w;
    edge[Top].next = head[u];
    head[u] = Top++;
}

LL dis[1010];

bool mark[1010];

struct Q
{
    int v;
    LL cost;
    bool operator < (const Q &a) const {
        return a.cost < cost;
    }
};

priority_queue<Q> q;

void Cal(int s,int n)
{
    memset(mark,false,sizeof(bool)*(n+2));

    Q f,t;

    for(int i = 1;i <= n; ++i)
        dis[i] = INF;

    f.v = s;
    f.cost = 0;

    q.push(f);

    while(q.empty() == false)
    {
        f = q.top();
        q.pop();

        if(mark[f.v])
            continue;
        mark[f.v] = true;

        dis[f.v] = f.cost;

        for(int p = head[f.v];p != -1; p = edge[p].next)
        {
            if(val[edge[p].v] > val[s])
                continue;

            t.v = edge[p].v;
            t.cost = edge[p].w + f.cost;
            if(dis[t.v] > t.cost)
            {
                dis[t.v] = t.cost; 
                q.push(t);
            }
        }
    }
}

int S[20010],T[20010];

LL Min[20010];

int main()
{
    int n,m,i,j,u,v;
    LL w;

    while(scanf("%d %d",&n,&m) && (n||m))
    {
        memset(head,-1,sizeof(int)*(n+2));
        Top = 0;

        for(i = 1;i <= n; ++i)
        {
            scanf("%lld",&val[i]);
        }
        for(i = 1;i <= m; ++i)
        {
            scanf("%d %d %lld",&u,&v,&w);
            Link(u,v,w);
            Link(v,u,w);
        }

        scanf("%d",&m);

        for(i = 0;i < m; ++i)
        {
            scanf("%d %d",&S[i],&T[i]);
            Min[i] = INF;
        }

        for(i = 1;i <= n; ++i)
        {
            Cal(i,n);
            for(w = 0;w < m; ++w)
            {
                Min[w] = min(Min[w],dis[S[w]] + dis[T[w]] + val[i]);
            }
        }

        for(i = 0;i < m; ++i)
        {
            if(Min[i] == INF)
                printf("-1\n");
            else
                printf("%lld\n",Min[i]);
        }

        printf("\n");
    }

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值