Problem A 表演
有$n$个有点权的点,$m$个有边权的边。对于每个点$u$,输出从这个点出发到$v$,其路径权值的两倍加上v的点权和最小的值。
对于$100\%$的数据,满足$1 \leq n,m \leq 2\times 10^5 $
Solution :
考虑一个简单的转移,$f[u]$表示点$u$的最小答案,最初$f[u]$ 为$u$的点权。
每一次更新,就是相邻的两个点$u,v$之间,用边权的两倍来更新答案。
如果在图上DP,那么就相当于,将初始这些点权加入priority_queue,跑最短路即可。
时间复杂度为$O(m log_2 n)$
# include <bits/stdc++.h> # define int long long using namespace std; const int N=2e5+10; struct rec{ int pre,to,w;}a[N<<1]; int n,m,tot; bool inq[N]; int head[N],d[N],val[N]; namespace Fast_IO { inline int read() { int x=0,w=0; char c=0; while (c<'0'||c>'9') w|=c=='-',c=getchar(); while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return w?-x:x; } void write(int x) { if (x<0) x=-x,putchar('-'); if (x>9) write(x/10); putchar('0'+x%10); } void writeln(int x) { write(x); putchar('\n'); } }; using namespace Fast_IO; void adde(int u,int v,int w) { a[++tot].pre=head[u]; a[tot].to=v; a[tot].w=w*2; head[u]=tot; } struct Node { int id,val; }; struct cmp { bool operator () (Node a,Node b) { return a.val > b.val; } }; priority_queue<Node,vector<Node>,cmp>q; void dijkstra() { for (int i=1;i<=n;i++) { d[i]=val[i]; inq[i]=true; q.push((Node){i,val[i]}); } while (q.size()) { int u=q.top().id; q.pop(); inq[u]=false; for (int i=head[u];i;i=a[i].pre) { int v=a[i].to; if (d[v]>d[u]+a[i].w) { d[v]=d[u]+a[i].w; if (!inq[v]) q.push((Node){v,d[v]}); } } } } signed main() { n=read();m=read(); for (int i=1;i<=m;i++) { int u=read(),v=read(),w=read(); adde(u,v,w); adde(v,u,w); } for (int i=1;i<=n;i++) val[i]=read(); dijkstra(); for (int i=1;i<n;i++) write(d[i]),putchar(' '); writeln(d[n]); return 0; }