分析:纯最短路径问题。
#include<cstdio>
#include<cstring>
#define max 1010
#define INF 0x3f3f3f //表示无穷大
int map[max][max],n;//map中存储长度,即是花费的时间
void dijkstra(int start,int end)
{
int dis[max], visit[max]; //dis[]是距离,,visit[]是访问标记,即选中为前驱的点,去除
int i,j,min,next=start;
for(i=1;i<=n;++i)
{
dis[i]=map[start][i]; //把start到各个点的距离 存储到dis[]中
visit[i]=0;
}
visit[start]=1; //标记
for(i=1;i<=n;++i)
{
min=INF;
for(j=1;j<=n;++j) //选择最小的点作为前驱
{
if(!visit[j] && min>dis[j])
{
next=j;
min=dis[j];
}
}
visit[next]=1; //把前驱点 标记
for(j=1;j<=n;++j)
{
if(!visit[j]) //没有被标记
{
if(dis[j]>dis[next]+map[next][j]) //dis[next]是前驱点,map[next][j]是通过前驱点往前延伸
{
dis[j]=dis[next]+map[next][j]; //更新距离
}
}
}
}
printf("%d\n",dis[end]);
}
int main()
{
int m,i,j,a,b,d,p,start,end;
while(scanf("%d%d",&n,&m)&&n||m)
{
for(i=1;i<=n;++i) //顶点编号
{
for(j=1;j<=n;++j)
{
if(i==j)
map[i][j]=0;//map中存储距离
else
map[i][j]=INF;
}
}
while(m--) //m行数据,完成输入花费时间
{
scanf("%d%d%d",&a,&b,&d);//a和b之间的距离,距离为d
if(map[a][b] > d) //map[][]中存储无穷大
{
map[a][b]=map[b][a]=d;
}
}
start=1,end=n;//输出开始的点,和结束的点
dijkstra(start,end);
}
return 0;
}
其他人解法:
spfa:
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #define INF 0x3f3f3f3f
- #define MAXN 100+10//点数
- #define MAXM 20000+10//边数
- using namespace std;
- int n,m,top,vis[MAXN],dis[MAXN],visit[MAXN],head[MAXN];
- struct node {
- int from,to,val,next;
- };
- node edge[MAXM];
- void init()//初始化邻接表
- {
- top=0;//建表从零开始
- memset(head,-1,sizeof(head));
- }
- void add(int u,int v,int w)//建立邻接表
- {
- edge[top].from=u;
- edge[top].to=v;
- edge[top].val=w;
- edge[top].next=head[u];
- head[u]=top++;
- }
- void spfa(int s)//s为源点
- {
- queue<int>q;//存储每次入队的点
- memset(vis,0,sizeof(vis));
- memset(dis,INF,sizeof(dis));//存储源点 到这个点的最短路
- vis[s]=1;//表示这个点是否在队列里面
- dis[s]=0;
- q.push(s);
- while(!q.empty())
- {
- int u=q.front();
- q.pop();
- vis[u]=0;//该点之后还可能进入队列 消除标记
- for(int i=head[u];i!=-1;i=edge[i].next)//遍历以u为起点的 所有边
- {
- int v=edge[i].to;
- if(dis[v]>dis[u]+edge[i].val)
- {
- dis[v]=dis[u]+edge[i].val;\
- if(!vis[v])
- {
- q.push(v);
- vis[v]=1;
- }
- }
- }
- }
- printf("%d\n",dis[n]);
- }
- void getmap()
- {
- while(m--)
- {
- int a,b,c;
- scanf("%d%d%d",&a,&b,&c);
- add(a,b,c);
- add(b,a,c);//无向图 既可由a->b,也可由b->a;
- }
- }
- int main()
- {
- while(scanf("%d%d",&n,&m),n|m)//n|m位运算符 n==0&&m==0时输入结束
- {
- init();
- getmap();
- spfa(1);
- }
- return 0;
- }
floyd:
- #include<stdio.h>
- #define INF 0x3f3f3f3f
- int n,m,path[110][110];
- void init()
- {
- for(int i=1;i<=n;i++)
- for(int j=1;j<=n;j++)
- {
- if(i==j)
- path[i][j]=0;
- else path[i][j]=INF;
- }
- }
- void floyd()
- {
- int i,j,k;
- for(k=1;k<=n;k++)//K是穷举i,j的断点 必须是最外层表示断点
- for(i=1;i<=n;i++)
- for(j=1;j<=n;j++)
- {
- if(path[i][j]>path[i][k]+path[k][j])
- path[i][j]=path[i][k]+path[k][j];
- }
- }
- void getmap()
- {
- int a,b,c;
- while(m--)
- {
- scanf("%d%d%d",&a,&b,&c);
- if(path[a][b]>c)//防止重复 一开始初始化为INF 若已经选过 则不满足if
- path[a][b]=path[b][a]=c;
- }
- }
- int main()
- {
- while(scanf("%d%d",&n,&m),n|m)
- {
- init();
- getmap();
- floyd();
- printf("%d\n",path[1][n]);
- }
- return 0;
- }