• 51 nod 1443 路径和树 【最短路径】


    51 nod 1443 路径和树

    Description

    给定一幅无向带权连通图G = (V, E) (这里V是点集,E是边集)。从点u开始的最短路径树是这样一幅图G1 = (V, E1),其中E1是E的子集,并且在G1中,u到所有其它点的最短路径与他在G中是一样的。

    现在给定一幅无向带权连通图G和一个点u。你的任务是找出从u开始的最短路径树,并且这个树中所有边的权值之和要最小。

    Input
    单组测试数据。
    第一行有两个整数n和m(1 ≤ n ≤ 3*10^5, 0 ≤ m ≤ 3*10^5),表示点和边的数目。
    接下来m行,每行包含3个整数 ui, vi, wi ,表示ui和vi之间有一条权值为wi的无向边(1 ≤ ui,vi ≤ n, 1 ≤ wi ≤ 10^9)。
    输入保证图是连通的。
    最后一行给出一个整数u (1 ≤ u ≤ n),表示起点。
    Output
    输出这棵树的最小的权值之和。
    Input示例
    3 3
    1 2 1
    2 3 1
    1 3 2
    3
    Output示例
    2

    题解:

    从rt开始的最短路径树顾名思义就是rt到其他节点的每条最短路径上的所有边构成的树

    这题一开始很容易想到,先跑一边最短路,然后再在这些边上最小生成树,但这样比较麻烦,而且容易T掉。
    实际上只要在跑SPFA的时候顺便记录下每个点的最小前驱,最后答案求和就行了。

    代码如下:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=3e5+5;
     4 const long long inf=1e18;
     5 int n,m,edge,nxt[2*N],to[2*N],hea[N];
     6 long long val[2*N];
     7 void add(int u,int v,long long w)
     8 {
     9     to[++edge]=v; nxt[edge]=hea[u]; hea[u]=edge; val[edge]=w;
    10     to[++edge]=u; nxt[edge]=hea[v]; hea[v]=edge; val[edge]=w;
    11 }
    12 long long dis[N],pre[N];
    13 bool vis[N];
    14 void spfa(int rt)
    15 {
    16     
    17     memset(vis,0,sizeof(vis));
    18     memset(pre,0,sizeof(pre));
    19     for (int i=1; i<=n; i++) dis[i]=inf;
    20     int q[3*N];
    21     int h=0,t=1;
    22     q[t]=rt; vis[rt]=true; dis[rt]=0;
    23     
    24     while (h<t)
    25     {
    26         int x=q[++h]; vis[x]=false;
    27         for (int i=hea[x]; i; i=nxt[i])
    28         {
    29             if (dis[to[i]]>dis[x]+val[i])
    30             {
    31                 dis[to[i]]=dis[x]+val[i];
    32                 pre[to[i]]=val[i];
    33                 if (!vis[to[i]])
    34                 {
    35                     vis[to[i]]=true; q[++t]=to[i];
    36                 }
    37             }
    38             else if (dis[to[i]]==dis[x]+val[i]) pre[to[i]]=min(pre[to[i]],val[i]);
    39         }
    40     }
    41 }
    42 int main()
    43 {
    44     scanf("%d%d",&n,&m);
    45     for (int i=1; i<=m; i++)
    46     {
    47         int u,v; long long w;
    48         scanf("%d%d%lld",&u,&v,&w);
    49         add(u,v,w);
    50     }
    51     int s;
    52     scanf("%d",&s);
    53     //cout<<"YES"<<endl;
    54     spfa(s);
    55     long long ans=0;
    56     for (int i=1; i<=n; i++)
    57       ans+=pre[i];
    58     printf("%lld
    ",ans);
    59     return 0;
    60 }
    View Code
    
    
    
    

    加油加油加油!!! fighting fighting fighting !!!

     
  • 相关阅读:
    ABP
    妖道角
    检测空值,以及会不会出现mapping类型不一致的问题
    wcf服务契约代理链
    wcf服务契约继承
    win64+anaconda+xgboost(转)
    python中迭代问题
    ROC曲线和AUC值(转)
    python中split()和split(' ')的区别
    str和repr的区别(转)
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9298629.html
Copyright © 2020-2023  润新知