/*dijkstra用于有权图,权值非负,起点终点已知,算法运行过程不断维护的关键信息是节点集合s。从源点(初始点)开始将路径最小的点u加入到集合s,不断重复该过程,终止条件是终点纳入集合s,他是贪心的策略但是正确的具体证明见算法导论第三版p385*/
/*题意为从1~n的最短路径*/
/*此题的坑主要是两点之间可能有重边在主函数中已解决详情见代码*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF=99999999;
int maps[1005][1005],v[1005],d[1005]; //v表示节点是(1)否(0)已纳入集合 | d表示当前这个集合最小值
int n;
void Dijkstra(int s,int t)
{
int i,j,k,mini;
for(i=1;i<=n;i++) d[i]=INF;
d[s]=0; //只有初始点的集合当然最小值为0
for(i=1;i<=n;i++) //该层循环是为了说明从起始点查找到终点的最短路径最多查找n个节点即查找次数(不用在意)
{
mini=INF;
k=-1; //纳入集合的将被标记,k为下标
for(j=1;j<=n;j++) //该层循环目的是 获得前驱节点的最小值并将前驱节点标记加入集合
{
if(!v[j] && d[j]<mini)
{
k = j;
mini = d[k];
}
}
v[k]=1;
if(k==t) //判断若终点t已经被标记为k,说明已经将重点纳入集合那么终止查找最短路
{
printf("%d\n",d[t]);
return;
}
for(j=1;j<=n;j++) //改成for循环的目的 寻找可纳入集合的下一个点
{
if(!v[j] && d[k]+maps[k][j]<d[j]) //前驱节点所在的结合d[k]向可纳入的下一个点的集合 d[k]+maps[k][j]的更新
{
d[j]=d[k]+maps[k][j];
}
}
}
}
void init()
{
memset(v,0,sizeof(v)); //清除标记
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
maps[i][j]=INF;
}
}
}
int main()
{
/*int T,i,j,x,y,D;
while(scanf("%d %d",&T,&n)!=EOF)
{
init();
for(i=1;i<=T;i++)
{
scanf("%d %d %d",&x,&y,&D);
if(maps[x][y]>D) //这里一点要注意,两个点之间未必只有一条边这里目的 若有重边那么此时已经选择了最短的边
maps[x][y]=D,maps[y][x]=D;
}
Dijkstra(1,n);
}*/
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF=99999999;
int maps[1005][1005],v[1005],d[1005];
int n;
void Dijkstra(int s,int t)
{
int i,j,k,mini;
for(i=1;i<=n;i++) d[i]=maps[s][i];//for(i=1;i<=n;i++) d[i]=INF;
//d[s]=0;
for(i=1;i<=n;i++)
{
mini=INF;
k=-1;
for(j=1;j<=n;j++)
{
if(!v[j] && d[j]<mini)
{
k = j;
mini = d[k];
}
}
v[k]=1;
if(k==t)
{
printf("%d\n",d[t]);
return;
}
for(j=1;j<=n;j++)
{
if(!v[j] && d[k]+maps[k][j]<d[j])
{
d[j]=d[k]+maps[k][j];
}
}
}
}
void init()
{
memset(v,0,sizeof(v)); //清除标记
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
maps[i][j]=INF;maps[i][i]=0;
}
}
}
int main()
{
return 0;
}