AcWing 4246. 最短路径和(反向建图+链式前向星+堆优化)
Posted MangataTS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 4246. 最短路径和(反向建图+链式前向星+堆优化)相关的知识,希望对你有一定的参考价值。
题目连接
https://www.acwing.com/problem/content/description/4249/
http://poj.org/problem?id=1511
思路
其实这道题和农场派对这题是一样的,我们反向建边就能求出所有其他点到1这个点的距离,然后直接加上去就好了,但是不同的是这题的数据非常大,所以如果你是使用vector
或者其他容器存储的话是会MLE的,所以我们这里手写链式前向星然后每次跑DJ的时候注意初始化就好了,下面放出两种写法的代码(第二种是MLE的)
代码
链式前向星+堆优化Djakarta
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
const int N=2e6+5;//数据范围
struct edge//存储边
int u,v,w,next;//u为起点,v为终点,w为权值,next为前继
;
edge e[N];
int head[N],dis[N],n,m,s,cnt;//head为链中最上面的,dis表示当前答案,n为点数,m为边数,s为起点,cnt记录当前边的数量
bool vis[N];//vis表示这个点有没有走过
struct node
int w,to;//w表示累加的权值,to表示到的地方
bool operator <(const node &x)const//重载“<”号
return w>x.w;
;
void add(int u,int v,int w)
++cnt;//增加边的数量
e[cnt].u=u;//存起点
e[cnt].v=v;//存终点
e[cnt].w=w;//存权值
e[cnt].next=head[u];//存前继
head[u]=cnt;//更新链最上面的序号
//链式前向星(加边)
void Dijkstra()
dis[s]=0;//起点到自己距离为0
priority_queue<node>q;//优先队列(堆优化)
q.push(node0,s);//压入队列
while(!q.empty())//队列不为空
node x=q.top();//取出队列第一个元素
q.pop();//弹出
int u=x.to;//求出起点
if(vis[u]) continue;//已去过就不去了
vis[u]=true;//标记已去过
for(int i=head[u];i;i=e[i].next)
int v=e[i].v;//枚举终点
if(dis[v]>dis[u]+e[i].w)//若中转后更优,就转
dis[v]=dis[u]+e[i].w;//更新
q.push(nodedis[v],v);//压入队列
int U[N],V[N],W[N];
void init()
int l = max(n,m);
for(int i = 1;i <= l; ++i)
head[i] = 0,vis[i] = false;
dis[i] = INF;
cnt = 0;
int main()
int u,v,w = 1;
s = 1;
int t;
scanf("%d",&t);
while(t--)
scanf("%d%d",&n,&m);//输入
init();
for(int i = 1;i <= m;++i)
scanf("%d%d%d",&U[i],&V[i],&W[i]);
add(U[i],V[i],W[i]);
Dijkstra();//DJ
long long ans = 0;
for(int i = 2;i <= n; ++i)
ans += dis[i];
init();
for(int i = 1;i <= m;++i)
add(V[i],U[i],W[i]);
Dijkstra();
for(int i = 2;i <= n; ++i)
ans += dis[i];
printf("%lld\\n",ans);
return 0;
使用容器存储
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
#define PII pair<int,int>
#define INF 0x3f3f3f3f
const int N = 1e6+10;
int dis[N],n,x,m;
struct Node
int v,w;
;
vector<Node> E[N];
bool vis[N];
void DJ(int s)
priority_queue<PII,vector<PII>,greater<PII> > que;
que.push(0,s);
dis[s] = 0;
while(!que.empty())
int t = que.top().second;
que.pop();
if(vis[t]) continue;
vis[t] = true;
for(int i = 0, l = E[t].size();i < l; ++i)
int j = E[t][i].v;
int w = E[t][i].w;
if(dis[j] > dis[t] + w)
dis[j] = dis[t] + w;
que.push(dis[j],j);
void init()
for(int i = 1;i <= n; ++i) vis[i] = false,dis[i] = INF;
for(int i = 1;i <= n; ++i) E[i].clear();
int U[N],V[N],W[N];
int main()
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--)
cin>>n>>m;
int u,v,w;
init();
for(int i = 1;i <= m; ++i)
cin>>U[i]>>V[i]>>W[i];
E[U[i]].push_back(V[i],W[i]);//正向建图
E[v].push_back(u,w);//反向建图
long long ans = 0;
DJ(1);
for(int i = 1;i <= n; ++i)
ans += dis[i];
init();
for(int i = 1;i <= m; ++i)
E[V[i]].push_back(U[i],W[i]);//反向建图
DJ(1);
for(int i = 1;i <= n; ++i)
ans += dis[i];
cout<<ans<<endl;
return 0;
以上是关于AcWing 4246. 最短路径和(反向建图+链式前向星+堆优化)的主要内容,如果未能解决你的问题,请参考以下文章