51nod 1443 路径和树(最短路树)

题目链接:路径和树

题意:给定无向带权连通图,求从u开始边权和最小的最短路树,输出最小边权和。

题解:构造出最短路树,把存留下来的边权全部加起来。(跑dijkstra的时候松弛加上$ < $变成$ <= $,因为之后跑到该顶点说明是传递下来的,该情况边权和最小。)

以样例作说明:第一次从顶点3跑到顶点1,最短路为2;第二次从顶点3经过顶点2跑到顶点1,最短路也为2,但是第二次跑的方式可以把从顶点3跑到顶点2的包括进去,这样形成的最短路树边权和最小。

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 typedef long long ll;
 9 const int N=3e5+10;
10 
11 struct qnode{
12     ll v,w;
13     qnode(){}
14     qnode(ll v,ll w):v(v),w(w){}
15     bool operator < (const qnode& b) const{
16         return w>b.w;
17     }
18 };
19 
20 struct node{
21     ll nxt,v,w;
22     node(){}
23     node(ll nxt,ll v,ll w):nxt(nxt),v(v),w(w){}
24 };
25 
26 ll n,m,tot,ans=0;
27 node edge[N<<1];
28 ll head[N],d[N],w[N];
29 qnode cur,tmp;
30 bool vis[N];
31 priority_queue <qnode> Q;
32 pair <ll,ll> fa[N];
33 vector <ll> g[N];
34 
35 void add_edge(ll u,ll v,ll w){
36     edge[tot]=node(head[u],v,w);
37     head[u]=tot++;
38 }
39 
40 void init(){
41     tot=1;
42     memset(head,0,sizeof(head));
43 }
44 
45 void dijkstra(ll s){
46     memset(vis,0,sizeof(vis));
47     for(int i=0;i<N;i++) d[i]=1e18;
48     d[s]=0;
49     Q.push(qnode(s,0));
50     while(!Q.empty()){
51         cur=Q.top();
52         Q.pop();
53         ll u=cur.v;
54         if(vis[u]) continue;
55         vis[u]=true;
56         for(ll i=head[u];i;i=edge[i].nxt){
57             ll v=edge[i].v;
58             ll w=edge[i].w;
59             if(d[u]+w<=d[v]){
60                 d[v]=d[u]+w;
61                 fa[v]=make_pair(u,(i+1)/2);
62                 Q.push(qnode(v,d[v]));
63             }
64         }
65     }
66 }
67 
68 void dfs(ll u,ll father){
69     for(ll v:g[u]){
70         if(v!=father) dfs(v,u);
71     }
72     ans+=w[fa[u].second];
73 }
74 
75 int main(){
76     init();
77     scanf("%lld%lld",&n,&m);
78     for(int i=1;i<=m;i++){
79         ll u,v;
80         scanf("%lld%lld%lld",&u,&v,&w[i]);
81         add_edge(u,v,w[i]);
82         add_edge(v,u,w[i]);
83     }
84     ll st;
85     scanf("%lld",&st);
86     dijkstra(st);
87     for(ll i=1;i<=n;i++){
88         if(st==i) continue;
89         g[fa[i].first].push_back(i);
90     }
91     dfs(st,0);
92     printf("%lld\n",ans);
93     return 0;
94 }
Code

猜你喜欢

转载自www.cnblogs.com/ehanla/p/9959968.html