zoukankan      html  css  js  c++  java
  • 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 !!!

     
  • 相关阅读:
    每日一水 POJ8道水题
    编译和使用 MySQL C++ Connector
    j2ee model1模型完成分页逻辑的实现 详解!
    DB查询分析器访问EXCEL时,要在表名前后加上中括弧或双引号
    指向结构体变量的指针
    EOSS V3.0 企业运营支撑系统(基于RBAC原理的权限管理)
    MybatisGen1.0 Mybatis JavaBean Mapper生成工具
    The table name must be enclosed in double quotation marks or sqare bracket while accessing EXCEL by
    资源-Android:Android
    软件-开发软件:Android Studio
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9298629.html
Copyright © 2011-2022 走看看