洛谷 P1821 [USACO07FEB] Cow Party S 最短路径spfa

48 篇文章 0 订阅
13 篇文章 3 订阅

1个多月没有发题解了

光顾着写算法了


题目描述
寒假到了, n 头牛都要去参加一场在编号为 x 的牛的农场举行的派对,农场之间有 m 条有向路,每条路都有一定的长度。
每头牛参加完派对后都必须回家,无论是去参加派对还是回家,每头牛都会选择最短路径,求这 n 头牛的最短路径(一个来回)中最长的一条路径长度。
输入格式
第一行有三个整数,分别表示牛的数量 n,道路数 m 和派对农场编号 x
接下来 m 行,每行三个整数 u, v, w,表示存在一条由 u 通向 v 的长度为 w 的道路。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #1
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
输出 #1
10

这题抽象起来很简单,明显的一个图论最短路径

唯一一个与正常的最短路径不一样的就是他求的是一个来回

并且是有向图,也就是说,去和回的最短路径也许不一样

于是大家兴高采烈的用dijkstra去了

超时了?没关系我还有优先队列

没错就是这么简单

AC了

# include <iostream>
# include <cstdio>
# include <cstring>
# include <queue>
# include <vector>
using namespace std;
# define int long long
int n,m,x,m2;
struct node{
    int to;
    int next;
    int w;
}e[100005];
struct node2{
    int idx,sum;
};
int adj[1005];
int f[1005];
int flag=0,v[1005],maxn=-1;
struct cmp{
    bool operator()(node2 &a,node2 &b){
        return a.sum>b.sum;
    }
};
priority_queue <node2 , vector<node2>,cmp> q;
void add(int u,int v,int w){
    m2++;
    e[m2].to=v;
    e[m2].next=adj[u];
    e[m2].w=w;
    adj[u]=m2;
}
bool relax(int u,int v,int w){
    if (f[v]>f[u]+w){
        f[v]=f[u]+w;
        return true;
    }
    return false;
}
void dijkstra(int s,int t){
    memset(f,0x3f,sizeof(f));
    memset(v,0,sizeof(v));
    f[s]=0;
    q.push(node2 {s,f[s]});
    while(!q.empty()){
        node2 cur=q.top();
        q.pop();
        if (v[cur.idx]){
            continue;
        }
        v[cur.idx]=1;
        for (int k=adj[cur.idx];k;k=e[k].next){
            int l=e[k].to;
            if (!v[l]){
                if (relax(cur.idx,l,e[k].w)){
                    q.push(node2{l,f[l]});
                }
            }
        } 
    }
}
signed main(){
    scanf("%lld%lld%lld",&n,&m,&x);
    for (int i=1;i<=m;i++){
        int u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
    }
    for (int i=1;i<=n;i++){
        if(i==x){
            continue;
        }
           dijkstra(i,x);
           int now_=f[x];
           dijkstra(x,i);
        now_+=f[i];
        if(now_>maxn){
            maxn=now_;
        }
    }
    printf("%lld",maxn);
    return 0;
}


如果你觉得有些水

没关系我也这么认为(doge)

有什么问题随时评论区问

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值