csu1808(优先级队列+Dijkstra)

解题思路 以边为单位计算 优先级队列存储与起点最短的边的长度

 #include  "set"
 #include  "queue"
 #include  "cmath"
 #include  "vector"
 #include  "cstdio" 
 #include  "cstring"
 #include  "cstdlib"
 #include  "iostream"
 #include  "algorithm"
 #include  "iostream"
 using namespace std; 
 #include  maxn 100002
 #include  len le18;
struct Edge //储存边的信息
{
    int a,b;
    long long c,t;
}edge[maxn];

struct node // 优先级队列的构造 
{
    int i;
    long long val;
};

bool operator<(node a,node b) // 优先级队列的构造 2
{
    return a.val>b.val;  //注意 "<"为从大到小排列,">"为从小到大排列 
};
vector<int>mrpe[maxn];
int vis[maxn];
long long dis[maxn];

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        int a,b;
        long long c,t;
        priority_queue<node> q;
        for(int i=0;i<=n;i++)
            mrpe[i].clear();
        memset(vis,0,sizeof(vis));
        for(int i=0;i<m;i++)
            dis[i]=len;// 初始化
        for(int i=0;i<m;i++)
        {
                   scanf("%d%d%lld%lld",&edge[i].a,&edge[i].b,&edge[i].c,&edge[i].t);
            if(min(edge[i].a,edge[i].b)==1)//判断是否为起点
            {
                dis[i]=edge[i].t;
                q.push(node{i,edge[i].t});
            }
            mrpe[edge[i].a].push_back(i);// mp存入边的信息
            mrpe[edge[i].b].push_back(i);
        }
        while(!q.empty()) //队列的使用
        {
            node na=q.top();
            int x=na.i; // 为最短的边
            //printf("%d\n",x);
            q.pop();
            if(vis[x])
               continue;
            vis[x]=1;
            int a=edge[x].a;
            int b=edge[x].b;
            for(int i=0;i<mrpe[a].size();i++) //更新与a对应邻近的边的值
            {
                int y=mrpe[a][i];
                long long val=edge[y].c-edge[x].c;
                if(val<0)
                   val=-val;
                if(dis[y]>dis[x]+val+edge[y].t){
                   dis[y]=dis[x]+val+edge[y].t;
                   q.push(node{y,dis[y]});
                }   
            }
            for(int i=0;i<mp[b].size();i++)  //更新与b邻近的边的值
            {
                int y=mrpe[b][i];
                long long val=edge[y].c-edge[x].c;
                if(val<0)
                   val=-val;
                if(dis[y]>dis[x]+val+edge[y].t){
                   dis[y]=dis[x]+val+edge[y].t;
                   q.push(node{y,dis[y]});
                }
            }
        }
        long long mis=1e18;
        for(int i=0;i<mp[n].size();i++)// 在n所有的边找最短的边
            mis=min(mis,dis[mrpe[n][i]]);
        printf("%lld\n",mis);
    }
    return 0;
}

// 多动手总会有收获加油

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值