标签:efi 比较 sharp def jks dijkstra clu max 搜索
我跟你讲SPFA已经死了好吧,SPFA+堆优又太难打,那就用dijkstra吧。(负权?我管它呢)
一般般快吧,N^2,N=10000时可以卡过,很好打。
#include <bits/stdc++.h>
#define MAXN 1005
using namespace std;
long long LIS[MAXN][MAXN];//LIS数组存储图
long long dis[MAXN];//dis数组,存储最短长度值
long long vis[MAXN];//vis[i]代表这个点有没有被当做源点去搜索过,1为有,0为没有。这样就不会重复搜索了。
long long N,M,S;
void dijkstra(long long x)//主函数,参数是源点编号
{
long long start=x;//先从源点搜索
for(long long i=1;i<=N;i++) dis[i]=LIS[x][i];//先更新一遍
dis[start]=0;
vis[start]=1;//标记源点已经搜索过
for(long long i=1;i<=N-1;i++)
{
long long MINN=2147483647;//比较
for(long long j=1;j<=N;j++) if(vis[j]==0&&MINN>dis[j]) MINN=dis[j],start=j;//找到离源点最近的点,然后把编号记录下来,用于搜索,可优化
vis[start]=1;
for(long long j=1;j<=N;j++) dis[j]=min(dis[j],dis[start]+LIS[start][j]);//以新的点来更新dis。
}
}
int main()
{
cin>>N>>M>>S;//N是点数,M是边数,S是出发点
for (long long i=1;i<=N;i++)for (long long j=1;j<=N;j++)LIS[i][j]=2147483647;
for (int i=1;i<=N;i++) LIS[i][i]=0;
for(long long i=1;i<=M;i++)
{
long long a,b,c;
cin>>a>>b>>c;
LIS[a][b]=min(LIS[a][b],c);//判重
//LIS[b][a]=min(LIS[a][b],c);//这是双向边
}
dijkstra(S);//以S为源点。
for(long long i=1;i<=N;i++) cout<<dis[i]<<" ";
return 0;
}
因为普通dijkstra需要找最小值然后更新,所以对于
for(long long j=1;j<=N;j++) if(vis[j]==0&&MINN>dis[j]) MINN=dis[j],start=j;
我们可以考虑用堆优化此过程,并且用链来存储,极大优化了内存
#include<bits/stdc++.h>
#define MAXN 100010
#define MAXM 200010
using namespace std;
long long last[MAXN],to[MAXM],nex[MAXM],v[MAXM],cnt=0,dis[MAXN];
bool vis[MAXN];
long long n,m,s;
void add(int x,int y,int w)
{
nex[++cnt]=last[x];//上一条边的编号
to[cnt]=y;//此边到哪个点
v[cnt]=w;//权值
last[x]=cnt;//以x开头的最后一条边的编号
}
priority_queue< pair<int,int> > q;
void dijkstra(int s)
{
for(int i=1;i<=n;i++) dis[i]=2147483647;//其实这样也可以,因为会自己更新的
dis[s]=0;
q.push(make_pair(0,s));//放入初始节点
while(!q.empty())//还未遍历完
{
int x=q.top().second;//堆头节点,最小节点编号
q.pop();//用过弹出
if(vis[x]) continue;//已拓展的就不要再做了
vis[x]=1;
for(int i=last[x];i;i=nex[i])//拓展
{
int y=to[i];//下一个点
if(dis[y]>dis[x]+v[i])
{
dis[y]=dis[x]+v[i];
q.push(make_pair(-dis[y],y));//用相反数实现小根堆,放入堆
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);//单向边
}
dijkstra(s);
for (int i=1;i<=n;i++) cout<<dis[i]<<" ";
return 0;
}
标签:efi 比较 sharp def jks dijkstra clu max 搜索
原文地址:https://www.cnblogs.com/GREED-VI/p/9882246.html