【打卡2】Dijkstra算法模板及例题

邻接矩阵版

const int MAXV=1000;//最大顶点数
const int INF=1000000000;
int n,G[MAXV][MAXV];//n为顶点数,MAXV为最大顶点数
int d[MAXV];//起点到达各点的最短路径长度
int pre[MAXV];//pre[v]表示从起点到顶点v的最短路径上v的前一个顶点
bool vis[MAXV]={false};//标记数组,vis[i]==true表示已访问。初值均为false

void Dijkstra(int s)//s为起点
{
    fill(d,d+MAXV,INF);//fill函数将整个d数组赋为INF
    d[s]=0;//起点s到达自身的距离为0
    for(int i=0;i<n;i++)//循环n次
    {
        int u=-1,MIN=INF;//u为距离最小的顶点序号,MIN存放该最小的d[u]
        for(int j=0;j<n;j++)
        {
            if(vis[j]==false&&d[j]<MIN)//找到未访问的顶点中距离最小的,一开始是起点
            {
                u=j;
                MIN=d[j];
            }
        }
        //找不到小于INF的距离,说明剩下的顶点和起点s不连通
        if(u==-1) return;
        vis[u]=true;//标记u为已访问
        for(int v=0;v<n;v++)
        {
            //如果v未访问&&能到达v&&以u为中介点可以使d[v]更优
            if(vis[v]==false&&G[u][v]!=INF&&d[u]+G[u][v]<d[v]){
                d[v]=d[u]+G[u][v];//优化v的距离
                pre[v]=u;//记录v的前驱顶点是u
        }
    }
}
void DFS(int s,int v)
{
	if(v==s)
	{
		printf("%d\n",s);
		return;
	}
	DFS(s,pre[v]);
	printf("%d\n",v);
}

邻接表版

struct Node
{
    int v,dis;
};
vector<Node> Adj[MAXV];
int n;
int d[MAXV];
bool vis[MAXV]={false};

void Dijkstra(int s)//s为起点
{
    fill(d,d+MAXV,INF);//fill函数将整个d数组赋为INF
    d[s]=0;//起点s到达自身的距离为0
    for(int i=0;i<n;i++)//循环n次
    {
        int u=-1,MIN=INF;//u为距离最小的顶点序号,MIN存放该最小的d[u]
        for(int j=0;j<n;j++)
        {
            if(vis[j]==false&&d[j]<MIN)//找到未访问的顶点中距离最小的,一开始是起点
            {
                u=j;
                MIN=d[j];
            }
        }
        //找不到小于INF的距离,说明剩下的顶点和起点s不连通
        if(u==-1) return;
        vis[u]=true;//标记u为已访问
        for(int j=0;v<Adj[u].size();j++)
        {
            int v=Adj[u][j].v;
            //如果v未访问&&以u为中介点可以使d[v]更优
            if(vis[v]==false&&d[u]+Adj[u][j].dis<d[v])
                d[v]=d[u]+Adj[u][j].dis;//优化v的距离
        }
    }
}

例题

  • 输入

输入的第一行包含2个正整数n和s,表示图中共有n个顶点,且源点为s。其中n不超过50,s小于n。
以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。

  • 输出

只有一行,共有n-1个整数,表示源点至其它每一个顶点的最短路径长度。如果不存在从源点至相应顶点的路径,输出-1。
请注意行尾输出换行。

  • 样例输入
4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
  • 样例输出
6 4 7 
  • 题解
#include 
#include
using namespace std;

const int MAXV=1000;//最大顶点数
const int INF=1000000000;
int n,G[MAXV][MAXV];//n为顶点数,MAXV为最大顶点数
int d[MAXV];//起点到达各点的最短路径长度
bool vis[MAXV]= {false}; //标记数组,vis[i]==true表示已访问。初值均为false

void Dijkstra(int s)//s为起点
{
    fill(d,d+MAXV,INF);//fill函数将整个d数组赋为INF
    d[s]=0;//起点s到达自身的距离为0
    for(int i=0; i<n; i++) //循环n次
    {
        int u=-1,MIN=INF;//u为距离最小的顶点序号,MIN存放该最小的d[u]
        for(int j=0; j<n; j++)
        {
            if(vis[j]==false&&d[j]<MIN)//找到未访问的顶点中距离最小的,一开始是起点
            {
                u=j;
                MIN=d[j];
            }
        }
        //找不到小于INF的距离,说明剩下的顶点和起点s不连通
        if(u==-1)
            return;
        vis[u]=true;//标记u为已访问
        for(int v=0; v<n; v++)
        {
            //如果v未访问&&能到达v&&以u为中介点可以使d[v]更优
            if(vis[v]==false&&G[u][v]!=0&&d[u]+G[u][v]<d[v])
                d[v]=d[u]+G[u][v];//优化v的距离
        }
    }
}

int main()
{
    int u;
    int s;
    while(scanf("%d%d",&n,&s)!=EOF)
    {
        fill(G[0],G[0]+MAXV*MAXV,INF);
        fill(vis,vis+MAXV,false);
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                scanf("%d",&u);
                G[i][j]=u;
            }
        }
        Dijkstra(s);
        for(int i=0; i<n; i++)
        {
            if(i!=s)
            {
                if(d[i]!=INF)
                    printf("%d ",d[i]);
                else
                    printf("-1 ");
            }
        }
        printf("\n");
    }

    return 0;
}

你可能感兴趣的:(保研机试【每日一题】)