#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define M 100000
#define MAX 0x3f3f3f
using namespace std;
struct Edge
{
int from,to,val,next;
};
Edge edge[MAX];
queue<int> q;
int head[220];
int dist[220];
int vis[220];
int n,m;
int edgenum;
void addedge(int u,int v,int w)
{
Edge E={u,v,w,head[u]};//这个定义是可以的,从别人那里借鉴来的
edge[edgenum]=E;
head[u]=edgenum++;
//printf("%d\n",edge[edgenum-1].next);
//printf("%d\n",head[u]);
//return 0;
}
void spfa(int s,int t)
{
//printf("%d\n",M);
//printf("%d\n",dist[2]);
int u,v;
int i;
dist[s]=0;
q.push(s);
vis[s]=1;
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;//每次出队列之后要把此点标记为未访问
for(i=head[u];i!=-1;i=edge[i].next)
{
//printf("%d\n",i);
v=edge[i].to;
if(dist[v]>dist[u]+edge[i].val)
{
dist[v]=dist[u]+edge[i].val;
//printf("%d\n",dist[v]);
if(!vis[v])//注意要判断此点是否已在队列内
{
q.push(v);
vis[v]=1; //标记此点已在队列内
}
}
}
}
if(dist[t]>=10000)
printf("-1\n");
else
printf("%d\n",dist[t]);
//return 0;
}
int main()
{
int i;
int a,b,c;
int s,t;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(head,-1,sizeof(head));
for(i=0;i<n;i++)
dist[i]=M;//用这个也不会费多少时间的
/*
此处最好不要用
#define INF 0x3f3f3f3f
memset(dist,INF,sizeof(dist));
因为会超过int型的存储范围,可以试着输出dist[2]的值于INF的值进行比较,是不相等的
而且题目当中说X的取值范围不大于10000,所以可以定义一个100000来初始化dist[220];
*/
memset(vis,0,sizeof(vis));
edgenum=0;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
/*
这里为什么要这样输入就跟spfa的算法本身有关了,
举个例子:
数据是 3 1
0 1 1
1 2
这个是什么意思可以去看题目的 ,将这些数据带入程序进行模拟,那么我们可以知道
第一步:点1对点2进行更新 ,此时点2进入队列
第二步:点2会对点1进行更新
差不多相当于map[1][2]=map[2][1],我们知道第一步是使用map[1][2],第二步是使用map[2][1]
所以在输入的时候要正反个输入一次
不过我们此处用的是邻接表,输入之后的数据是这样的
0 1 1 edge[0]=E edge[0].next=E.head[0]=-1 edgenum=1; head[0]=0
1 0 1 edge[1]=E edge[1].next=E.head[1]=-1 edgenum=2; head[1]=1;
此处注意E.head[]跟head[]是不相等的
正面和反面的输入的val值是不变的,所以在进行正反更新的时候是不会影响的,这个跟邻接表的性质有关
我觉得他们之间的连接与应用真的是太巧妙了
*/
}
scanf("%d%d",&s,&t);
spfa(s,t);
}
return 0;
}
hdu 1874 畅通工程续-spfa
最新推荐文章于 2019-08-08 22:15:00 发布