zoukankan      html  css  js  c++  java
  • 单源起点最短路SPFA——pku3013

    思路:
    可能从题意去解决问题比较棘手,换个角度,实际就是各个(顶点到根节点的最短路*该顶点的权值)的和,类似usaco2.4.4
    此题注意点:
    1、用int型会超范围,(50000*2^16)>(1<31)
    2、用SPFA算法是要注意无向图边的数量是题目所说边的两倍,因为这个看似简单的地方,RE了n久
    3、还有就是判断No Answer是只在节点到起点(也就是根节点)没有路时才成立,注意max==0时结果是0,不是No Answer!!!
    View Code
    #include<iostream>
    #include
    <queue>
    using namespace std;

    const __int64 maxn=0xffffffffff;
    const __int64 edge_maxn = 100111; //边的最大上限 一定要注意无向图的边是有向图的两倍
    const __int64 point_maxn =50111; //点的最大上限
    struct node
    {
    __int64 v;
    //终点
    __int64 w;//权值
    __int64 next;//同一起点的下一条边在edge数组中的位置
    }edge[edge_maxn];
    __int64 pre[point_maxn];
    //以该点为起点的最后一条边存储在edge数组中的位置
    __int64 n;//点的数量
    __int64 m;//边的数量
    queue<__int64>Q;
    __int64 dirs[point_maxn];
    //起点到i的最短距离
    bool vis[point_maxn];//是否存在于队列

    __int64 p[point_maxn];
    void Init()
    {
    memset(pre,
    -1,sizeof(pre));
    __int64 x,y,z;
    __int64 index
    =1;
    __int64 i,j;
    for(i=1;i<=m;i++)
    {
    scanf(
    "%I64d%I64d%I64d",&x,&y,&z);
    edge[index].v
    =y;
    edge[index].w
    =z;
    edge[index].next
    =pre[x];
    pre[x]
    =index++;//保存x起点的最后一条边在edge数组中的位置
    swap(x,y);
    edge[index].v
    =y;
    edge[index].w
    =z;
    edge[index].next
    =pre[x];
    pre[x]
    =index++;
    }
    }

    void SPFA()
    {
    __int64 start
    =1;
    while(!Q.empty())
    {
    Q.pop();
    }

    memset(vis,
    0,sizeof(vis));
    fill(dirs,dirs
    +point_maxn,maxn);
    dirs[start]
    =0;
    vis[start]
    =1;
    Q.push(start);
    while(!Q.empty())
    {
    unsigned
    int top=Q.front();//边的起点
    Q.pop();
    vis[top]
    =0;
    for(int j=pre[top];j!=-1;j=edge[j].next)//pre[x]以该点为起点的最后一条边存储在edge数组中的位置
    {
    __int64 e
    =edge[j].v;//边的终点
    if(dirs[e]>edge[j].w+dirs[top])
    {
    dirs[e]
    =edge[j].w+dirs[top];
    if(!vis[e])
    {
    Q.push(e);
    vis[e]
    =1;
    }
    }
    }
    }
    }
    int main()
    {
    __int64 t,i;
    __int64 max;
    scanf(
    "%I64d",&t);
    while(t--)
    {
    scanf(
    "%I64d%I64d",&n,&m);
    for(i=1;i<=n;i++)
    {
    scanf(
    "%I64d",&p[i]);
    }
    Init();
    SPFA();

    max
    =0;
    int rt=0;
    for(i=2;i<=n;i++)//要从2开始
    {
    if(dirs[i]==maxn)
    {
    printf(
    "No Answer\n");
    rt
    =1;
    break;
    }
    max
    +=p[i]*dirs[i];
    }
    if(rt==0)
    {
    if(max==0)
    {
    printf(
    "0\n");//注意max==0时结果是0,不是No Answer,错了n久
    continue;
    }
    else
    printf(
    "%I64d\n",max);
    }
    }
    return 0;
    }
  • 相关阅读:
    【JS】415- JS面向对象之 7 大基本原则
    【每周小回顾】14- 一起回顾上周精彩内容
    【全栈修炼】414- CORS和CSRF修炼宝典
    【全栈修炼】CORS和CSRF修炼宝典
    【JS】413- JavaScript中的位运算和权限设计
    【面试题】412- 35 道必须清楚的 React 面试题
    【CSS】410- 关于CSS盒子模型、BFC及其应用
    15.app后端怎么设计用户登录方案
    14.app后端如何设计api
    13.app后端为什么要用到消息队列
  • 原文地址:https://www.cnblogs.com/huhuuu/p/1956213.html
Copyright © 2011-2022 走看看