感觉这道题和上一道有点相似
思路:
数据结构:链式前向星
1.读取数据。正常读取就可以了,把图构造出来
2.从编号为c的点开始递归
递归函数
参数:node当前访问的点,从出发点到当前的点的距离dis
直接标记当前结点
如果dis>mindis[node]
取消标记
直接return,说明不是最优解
其它情况,则访问和这个点相连的所有结点(访问过的结点就不要再访问了吧?)
如果没有被标记,那么递归即可,dis+edge[i].dis;
输出mindis[i] (i!=c);
拿了40分
三个TLE
三个RE
RE愿意是我数组开小了
开回来之后
成功得到6个TLE,
还行,说明我算法出现问题
单源最短路径。。嗯。。。
标签中出现了这个:SPFA
interesting
学习一下,看了b站上面的教程感觉就是一个记忆化+BFS?
也就是
如果起点到当前点的距离加上当前点和其所连点的距离小于等于起点到所连点的距离,那么就要更新最小值,并且把这个相连的点入队,等待进行广搜
和广搜的区别就是,一个点可以两次进入队列
也就是如果一个点进入过队列,出去了,那么之后这个点还可以进来
对照了答案,怎么出错了呢?
可以说是一模一样了
气死我了气死我了气死我了气死我了!!!!!!!
数组开小了,题目描述不是很清晰
放代码
#include<stdio.h>
typedef struct
{
int endNode,dis,nextEdge;
}Edge;
Edge edge[500100];
const int inf=2147483647;
int n,m,start,from,to,dis,cnt=0,head[101000]={0},tag[101000]={0},line[101000]={0},headl=1,tail=1;
int mindis[101000]={0};
void createdge(int from,int to,int dis);
int main()
{
scanf("%d %d %d",&n,&m,&start);
for(int i=1;i<=m;i++)//读取边
{
scanf("%d %d %d",&from,&to,&dis);
createdge(from,to,dis);
}
//初始化mindis
for(int i=1;i<=n;i++)
{
mindis[i]=inf;//最大值
}
mindis[start]=0;
// dfs(start,0);
//初始操作,把搜索点入队
line[tail]=start;
tag[start]=1;
while(1)
{
if(headl>tail)
{
break;
}
//取出队首元素,把这个清空标记
int st=line[headl];
headl++;
tag[st]=0;
//遍历和队首元素相连的所有结点
for(int i=head[st];i;i=edge[i].nextEdge)
{
//如果当前结果小于最优结果,进行深搜即可
int to=edge[i].endNode;
if(mindis[st]+edge[i].dis<mindis[to])
{
mindis[to]=mindis[st]+edge[i].dis;
if(tag[to]==0)//把这个结点入队
{
tag[to]=1;
tail++;
line[tail]=to;
}
}
}
}
for(int i=1;i<=n;i++)
{
if(mindis[i]==inf)
{
printf("%d ",inf);
}
else
{
printf("%d ",mindis[i]);
}
}
return 0;
}
void createdge(int from,int to,int dis)
{
cnt++;
edge[cnt].nextEdge=head[from];
edge[cnt].endNode=to;
edge[cnt].dis=dis;
head[from]=cnt;
}