[USACO09DEC]牛收费路径Cow Toll Paths

题意

有一张无向无环连通图,点和边均有权值。一条路径的值等于路径上点的最大值加上边之和。

多次询问,两点之间路径最小值。


思路

每个点跑一遍dijkstra,判断是否取点加入点值。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T> inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }
    template<typename T> inline void write (T x) {
        if (x<0) putchar('-'),x=-x;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Solve {
    #define int long long
    
    const int N=300;
    const int INF=0x3f3f3f3f3f3f3f3f;
    
    int n,m,k;
    int G[N][N];
    struct node {
        int to,val;
        node () {to=val=0;}
        node (int x,int v) : to(x),val(v) {}
        friend bool operator < (node a,node b) {
            if (a.val!=b.val) return a.val>b.val;
            return a.to>b.to;
        }
    };
    int c[N];
    int dis[N][N];

    inline void dijkstra (int a) {
        priority_queue<node> Q;
        Q.push(node(a,0));
        while (!Q.empty()) {
            node now=Q.top();Q.pop();
            if (dis[a][now.to]!=INF) continue;
            dis[a][now.to]=now.val;
            for (register int i=1; i<=n; ++i) {
                if (c[i]>c[a]||G[now.to][i]==INF) continue;
                Q.push(node(i,G[now.to][i]+dis[a][now.to]));
            }
        }
    }
    
    inline void MAIN () {
        memset(G,0x3f,sizeof(G));
        memset(dis,0x3f,sizeof(dis));
        read(n),read(m),read(k);
        for (register int i=1; i<=n; ++i) {
            read(c[i]),G[i][i]=0;
        }
        for (register int i=1; i<=m; ++i) {
            int x,y,z;
            read(x),read(y),read(z);
            G[x][y]=G[y][x]=min(G[x][y],z);
        }
        for (register int i=1; i<=n; ++i) dijkstra(i);
        while (k--) {
            int s,t,ans=INF;
            read(s),read(t);
            for (register int i=1; i<=n; ++i) {
                if (c[i]>=c[s]&&c[i]>=c[t]) {
                    ans=min(ans,dis[i][s]+dis[i][t]+c[i]);
                }
            }
            write(ans),putchar('\n');
        }
    }
    
    #undef int
}

int main () {
    Solve::MAIN();
}

转载于:https://www.cnblogs.com/ilverene/p/11368727.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值