zoukankan      html  css  js  c++  java
  • 【最短路径树】51nod1443 路径和树

    并不是什么高端操作并且一些模型会用到

    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

    题目大意

    求最短路径树的最小权值和

    题目分析

    最短路径树是原图的一种生成树。注意以不同的点为根产生的最短路径树是不一样的(道理同最短路)。

    这里要求的是“最小权值和”,听上去好像很麻烦的样子:要把跑的最短路的边拎出来,再做一遍最小生成树……

    但是实际上我们发现它是满足贪心性质的,并且并不会影响后面元素的取值。

    所以只需要维护一个$pre[i]$表示转移到$i$的最小边权,然后在dij过程中再加一句判断就可以了。

    来自hzq的告诫:“能用堆优化dij就用堆优化的dij,SPFA尽量尽量不要写。系统堆优化的dij有这么难写吗?”

     1 #include<bits/stdc++.h>
     2 typedef long long ll;
     3 const int maxn = 300035;
     4 const int maxm = 600035;
     5 const ll INF = 1152921504606846976;
     6 
     7 ll dis[maxn],pre[maxn],ans;
     8 struct cmp
     9 {
    10     bool operator ()(int a, int b) const
    11     {
    12         return dis[a] > dis[b];
    13     }
    14 };
    15 struct Edge
    16 {
    17     int y;
    18     ll val;
    19     Edge(int a=0, ll b=0):y(a),val(b) {}
    20 }edges[maxm];
    21 int n,m,s;
    22 int head[maxn],nxt[maxm],edgeTot;
    23 std::priority_queue<int, std::vector<int>, cmp> q;
    24 
    25 int read()
    26 {
    27     char ch = getchar();
    28     int num = 0;
    29     bool fl = 0;
    30     for (; !isdigit(ch); ch = getchar())
    31         if (ch=='-') fl = 1;
    32     for (; isdigit(ch); ch = getchar())
    33         num = (num<<1)+(num<<3)+ch-48;
    34     if (fl) num = -num;
    35     return num;
    36 }
    37 void addedge(int u, int v, ll w)
    38 {
    39     edges[++edgeTot] = Edge(v, w), nxt[edgeTot] = head[u], head[u] = edgeTot;
    40 }
    41 int main()
    42 {
    43     memset(head, -1, sizeof head);
    44     n = read(), m = read();
    45     for (int i=1; i<=m; i++)
    46     {
    47         int u = read(), v = read(), w = read();
    48         addedge(u, v, w), addedge(v, u, w);
    49         dis[i] = INF;
    50     }
    51     s = read(), q.push(s), dis[s] = 0;
    52     while (q.size())
    53     {
    54         int tt = q.top();
    55         q.pop();
    56         for (int i=head[tt]; i!=-1; i=nxt[i])
    57         {
    58             int v = edges[i].y;
    59             ll w = edges[i].val;
    60             if (dis[v] > dis[tt]+w||(dis[v]==dis[tt]+w&&pre[v] > w))
    61                 dis[v] = dis[tt]+w, pre[v] = w, q.push(v);
    62         }
    63     }
    64     for (int i=1; i<=n; i++)
    65         ans += pre[i];
    66     printf("%lld
    ",ans);
    67     return 0;
    68 }

    END

  • 相关阅读:
    ThinkDev组件库 开篇
    使用 CodeIgniter 框架快速开发 PHP 应用(六)
    使用 CodeIgniter 框架快速开发 PHP 应用(五)
    jQuery EasyUI 的截图插件(imgAreaSelect)用法
    细说UI线程和Windows消息队列
    ASP.NET MVC2 异常处理机制中令人费解的HTTP 500错误
    从了解到深入——剖析WF4的数据流
    .NET 4.0中数组的新增功能
    成功就是把自己的特长发挥得淋漓尽致(更新)
    WPF4数据绑定应用之“创建具有多种显示效果的字串”
  • 原文地址:https://www.cnblogs.com/antiquality/p/9301766.html
Copyright © 2011-2022 走看看