文章标题

ZOJ-3946 Highway Project

思路:简单的单源最短路径(dijkstra模板),dij[i]数组用于记录源点到城市i的最小time,cost[i]记录从某一前置城市到达城市i的最小花费(满足time的前提);更新dij[i]时必须更新cost[i],遇到与当前dij[i]相同时,更新cost[i]更新为较小值。
题目链接

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long 
#define mod 998244353
#define eps 1e-6
double pi=acos(-1);
const ll INF=1e12;
#define MAXN 100009
struct node{
    int city;
    ll time,cost;
    node(int c,ll t,ll co){
        city=c;time=t;cost=co;
    }
    bool operator < (const node &a) const {  
        return time > a.time;//最小值优先  
    }  
};
ll dij[MAXN],cost[MAXN];//time,cost
int n;
bool flag[MAXN];
vector<node> ma[MAXN];//邻接表
priority_queue<node> que;//优先队列
void dijkstra(int sourse){
    int i,u,v;
    ll w,c;
    for(i=0;i<n;i++){
        dij[i]=(i==0?0:INF);//初始化
        cost[i]=(i==0?0:INF);
    }
    memset(flag,false,sizeof(flag));
    while(!que.empty()){
        que.pop();
    }
    que.push(node(0,0,0));
    while(!que.empty()){
        node pa=que.top();
        que.pop();
        u=pa.city;
        if(flag[u]){
            continue;
        }
        flag[u]=true;
        int len=ma[u].size();
        for(i=0;i<len;i++){
            v=ma[u][i].city;
            w=ma[u][i].time;
            c=ma[u][i].cost;
            if(dij[v]>dij[u]+w){
                dij[v]=dij[u]+w;
                cost[v]=c;
                if(!flag[v]){
                    que.push(node(v,dij[v],c));
                }

            }
            else if(dij[v]==dij[u]+w){
                if(cost[v]>c){
                    cost[v]=c;
                }
            }
        }
    }
    ll ret=0,Cost=0;
    for(i=0;i<n;i++){
        ret+=dij[i];
        Cost+=cost[i];
    }
    printf("%lld %lld\n",ret,Cost);
    return;
}

int main()
{   

    int T,m,i;
    int u,v;
    ll w,c;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)ma[i].clear();
        for(i=0;i<m;i++){
            scanf("%d%d%lld%lld",&u,&v,&w,&c);
            ma[u].push_back(node(v,w,c));
            ma[v].push_back(node(u,w,c));
        }
        dijkstra(0);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值