[51nod1143] 路径和树

题意:给出一个图,要你构出最短路树

题解:

spfa

和上次那个题一样,一条边只会松弛一个点,spfa的同时记录每个点被哪条边松弛

将这些边加入答案即可

注意一下边的范围,没long long,wa了几次......

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #define ll long long
 9 using namespace std;
10
11 const int N = 300010;
12
13 ll ans=0,dis[N];
14 int n,m,e_num,s;
15 int nxt[N*2],to[N*2],w[N*2],h[N],pre[N];
16 bool in[N];
17
18 queue<int> q;
19
20 inline int gi() {
21   int x=0,o=1; char ch=getchar();
22   while(ch!=‘-‘ && (ch<‘0‘ || ch>‘9‘)) ch=getchar();
23   if(ch==‘-‘) o=-1,ch=getchar();
24   while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
25   return o*x;
26 }
27
28 inline void add(int x, int y, int z) {
29   nxt[++e_num]=h[x],to[e_num]=y,w[e_num]=z,h[x]=e_num;
30 }
31
32 inline void spfa() {
33   memset(dis,63,sizeof(dis));
34   dis[s]=0,in[s]=1,q.push(s);
35   while(!q.empty()) {
36     int u=q.front();
37     in[u]=0,q.pop();
38     for(int i=h[u]; i; i=nxt[i]) {
39       int v=to[i];
40       if(dis[u]+w[i]<dis[v]) {
41       pre[v]=i;
42       dis[v]=dis[u]+w[i];
43       if(!in[v]) in[v]=1,q.push(v);
44       }
45       else if(dis[u]+w[i]==dis[v]) {
46       if(w[i]<w[pre[v]]) pre[v]=i;
47       }
48     }
49   }
50 }
51
52 int main() {
53   n=gi(),m=gi();
54   for(int i=1; i<=m; i++) {
55     int x=gi(),y=gi(),z=gi();
56     add(x,y,z),add(y,x,z);
57   }
58   s=gi(),spfa();
59   for(int i=1; i<=n; i++) {
60     if(i==s) continue;
61     ans+=w[pre[i]];
62   }
63   printf("%lld\n", ans);
64   return 0;
65 }
时间: 2024-10-20 12:16:29

[51nod1143] 路径和树的相关文章

[BZOJ 1576] 安全路径 最短路径树 路径压缩

题意 给定一张 n 个点 m 条边的图, 保证对于任意的点 i , 从点 1 到点 i 的最短路唯一. 对于任意的点 i , 询问: 将 1 到 i 的最短路中最后一条边删去之后, 从 1 到 i 的最短路 . n <= 100000, m <= 200000 . 分析 首先跑 Dijsktra , 构建出最短路径树. 接下来考虑每条非树边 E[p] = (u, v, d) 对答案的影响, 它能且仅能影响到点 u, v 之上, LCA(u, v) 之下的点的答案. (包括 u, v, 不包括

[51nod1443]路径和树

给定一幅无向带权连通图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 ,

51Nod 1443 路径和树

还是一道很简单的基础题,就是一个最短路径树的类型题目 我们首先可以发现这棵树必定满足从1出发到其它点的距离都是原图中的最短路 换句话说,这棵树上的每一条边都是原图从1出发到其它点的最短路上的边 那么直接跑最短路,SPFA,不存在的?我只信DJ,然后记录那些边在最短路上 然后直接跑MST即可.是不是很经典的水题 然后我又莫名拿了Rank1(没办法天生自带小常数) CODE #include<cstdio> #include<cctype> #include<cstring>

【51nod1443】路径和树(堆优化dijkstra乱搞)

点此看题面 大致题意:给你一个无向联通图,要求你求出这张图中从u开始的权值和最小的最短路径树的权值之和. 什么是最短路径树? 从\(u\)开始到任意点的最短路径与在原图中相比不变. 题解 既然要求最短路径,那么最容易想到的就是\(dijkstra\)和\(SPFA\)(毕竟Floyd的时间复杂度难以承受),又由于黄学长说能用\(dijkstra\)时尽量用\(dijkstra\),所以,我就打了一个堆优化的\(dijkstra\)开始乱搞. 其实,这道题目的思路真的挺简单的,只要朴素地做一遍\(

安全路径——最短路径树+dsu缩边

题目描述 思路 首先想到$dijkstra$跑完之后$build$一棵最短路径树.要找到每个节点i到根的满足要求的最短路,考虑把一些非树边加进去. 对于非树边$(u,v)$,因为节点i上方的边被占领,所以只能选择往下走,从非树边走到别的子树,设$u$属于$i$的子树,$v$不属于,那么$u,v$的$lca$经过$i$,且$i$经过$(u,v)$到根的最短路为$dist[u]+dist[v]-dist[i]+w(u,v)$,这样我们把每条非树边按照$dist[u]+dist[v]+w(u,v)$排

51nod 1443 路径和树——最短路生成树

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1443 不只是做一遍最短路.还要在可以选的边里选最短的才行. 以为是求一遍最短路,然后按边权对边排序,哪条边两边的dis正好吻合,就把该边的边权加到ans里,把两端加到并查集里. 但其实不对.因为忽略了方向.比如如果有多个点同样地可以更新一个点,算的时候可能这多个点都因为那个点而被合到了并查集里,但其实只能有一个被合进去. 其实只要松弛点的时候如果dis[v]==d

hdu2196 Computer(树的直径||树中的最长路径)

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5232    Accepted Submission(s): 2640 Problem Description A school bought the first computer some time ago(so this computer's id is 1). D

《数据结构与算法分析》第四章--树 (1)

4.1 预备知识 定义: 树的递归定义:一棵树是一些节点的集合,这个集合若为空集:否则由一个根结点以及该节点的0个或者若干个非空子树组成,这些子树都与该根节点有边连接. 树叶:没有子节点的节点. 兄弟(Siblings):有相同父亲节点的节点. 节点n1到nj的路径:一个节点 序列:n1,n2...,nj. 路径的长:路径上的边数. 节点ni的深度:根节点到ni的唯一路径的长.根节点深度为0. 节点ni的高度:该节点ni到叶子节点的最长路径.树的高:根节点的高度. 4.1.1 树的实现 左孩子右

【数据结构】基数树

本节研究基数树相关的机制和实现: 基数树 说明几点 (1)基数树,是一种基于二进制表示键值的二叉查找树,类似字典树:其典型应用为IP地址的查找: (2)如果使用IPv4时,基数树只需要支持到最大深度为32就可以了,key值从最高位向最低位开始匹配,比如key为0xC0000000,将会从key的最高位1向0开始匹配: 代码分析 (本节代码选自Nginx中关于基数树的代码) 基数树声明 //基数树节点 struct ngx_radix_node_s { ngx_radix_node_t *righ