2208: 短
题目描述
给出无向图G=(V,E),求点V1和点VN之间的最短路。
输入
第一行两个整数|V|和|E|。
2~E+1行,每行3个整数Xi,Yi,Wi,表示点Vxi和点Vyi之间存在权值为Wi的边。
输出
一个整数表示最短路的权值。
样例输入
3 3
1 2 1
2 3 1
3 1 1
样例输出
1
提示
对于50%的数据,V<=103。
对于100%的数据,V<=105,E<=106,1<=Wi<=2。
此题V<=10^5,E<=10^6,所以有Dij堆优化和spfa两种算法.
今天我写一个spfa算法
#include<stdio.h>
#include<string.h>
int idx;
struct Edge
{
int val,to,next;
};
Edge edge[2000001];//edge[i].val表示边权是多少,edge[i].to表示到达谁,edge[i].next表示下一个是谁.存双向边数组要开2倍
int head[2000001];
int f[1000001];
int queue[4000001];
bool used[1000001];
void addedge(int a,int b,int c)//链表存边
{
edge[++idx].next=head[a];
head[a]=idx;
edge[idx].to=b;
edge[idx].val=c;
}
int main()
{
int n,e,i,j,a,b,c;
scanf("%d%d",&n,&e);
for(i=1;i<=e;i++)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);//调用函数
}
int front=0,tail=0;
queue[tail++]=1;
memset(f,1,sizeof(f));
f[1]=0;
memset(used,0,sizeof(used));
used[1]=1;
while(front<tail)//spfa核心,used[i]表示是否进入队列
{
int idx2=queue[front++];
used[idx2]=0;
for(j=head[idx2];j;j=edge[j].next)
{
if(f[edge[j].to]>f[idx2]+edge[j].val)
{
f[edge[j].to]=f[idx2]+edge[j].val;
if(used[edge[j].to]==0)
{
queue[tail++]=edge[j].to;
used[edge[j].to]=1;
}
}
}
}
printf("%d",f[n]);
}