dij板子的灵活运用
在一个有向图中求:1.1号点到剩下所有点的最短路 2.剩下所有点到一号点的最短路
1相信谁都会,存有向图跑一遍
2是这道题的精髓,应用一个比较有价值的思想:在有向图中跑反向边,相当于求出所有点到一号点的最短路
所以简单说就是存两个版本的图然后两遍dij板子
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define ll long long #define re register #define il inline #define inf 214748364 #define fp(i,a,b) for(re int i=a;i<=b;i++) #define fq(i,a,b) for(re int i=a;i>=b;i--) using namespace std; int n,m,h[1000005],cnt=0,inq[1000005]={},dis[1000005]={},h1[1000005]={}; ll ans=0; struct Edge { int to,next,w; }e[1000005],e1[1000005]; struct Node { int l,d; Node(){} Node(int l,int d):l(l),d(d){} bool operator < (const Node& zsy) const { return l>zsy.l; } }; il void add(re int u,re int v,re int w) { e[++cnt]=(Edge){v,h[u],w};h[u]=cnt; } il void add1(re int u,re int v,re int w) { e1[cnt]=(Edge){v,h1[u],w};h1[u]=cnt; } il void Dijkstra() { fp(i,1,n) dis[i]=inf; dis[1]=0; priority_queue<Node>Q; Q.push(Node(0,1)); while(!Q.empty()) { Node u=Q.top();Q.pop(); if(inq[u.d]) continue; inq[u.d]=1; for(re int i=h[u.d];i+1;i=e[i].next) { re int v=e[i].to,w=e[i].w; if(u.l+w<dis[v]) { dis[v]=u.l+w; Q.push(Node(dis[v],v)); } } } } il void Dijkstra1() { fp(i,1,n) dis[i]=inf; dis[1]=0; memset(inq,0,sizeof(inq)); priority_queue<Node>Q; Q.push(Node(0,1)); while(!Q.empty()) { Node u=Q.top();Q.pop(); if(inq[u.d]) continue; inq[u.d]=1; for(re int i=h1[u.d];i+1;i=e1[i].next) { re int v=e1[i].to,w=e1[i].w; if(u.l+w<dis[v]) { dis[v]=u.l+w; Q.push(Node(dis[v],v)); } } } } int main() { memset(h,-1,sizeof(h));memset(h1,-1,sizeof(h1)); scanf("%lld%lld",&n,&m); fp(i,1,m) { ll u,v,w; scanf("%lld%lld%lld",&u,&v,&w); add(u,v,w); add1(v,u,w); } Dijkstra(); fp(i,2,n) ans+=dis[i]; Dijkstra1(); fp(i,2,n) ans+=dis[i]; printf("%lld\n",ans); return 0; }
原文地址:https://www.cnblogs.com/charlesss/p/10742547.html
时间: 2024-11-11 05:43:51