HDOJ 2544 最短路(四种做法)

优化后的SFPA和Dijkstra:

SPFA模板:
```
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 100005;
struct edge{
    int to,nxt,w;
    edge(int t=0,int n=0,int w=0):to(t),nxt(n),w(w){}
}E[N*5];
int tot,head[N*5];
int vis[N],d[N];
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int w)
{
    E[tot] = edge(v,head[u],w);
    head[u] = tot++;
}
void SPFA(int s)
{
    memset(vis,0,sizeof(vis));
    memset(d,0x3f,sizeof(d));
    queue<int> q;
    q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!q.empty())
    {
        int u = q.front();q.pop();
        vis[u] = 0;
        for(int i = head[u];~i;i = E[i].nxt)
        {
            int v = E[i].to,w = E[i].w;
            if(d[v] > d[u] + w)
            {
                d[v] = d[u] + w;
                if(!vis[v])
                {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    int n,m,u,v,w;
    while(~scanf("%d%d",&n,&m) && (n || m))
    {
        init();
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        SPFA(1);
        printf("%d\n",d[n]);
    }
    return 0;
}
```
Dijkstra:
```
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 100005;
struct edge{
    int to,nxt,w;
    edge(int t=0,int n=0,int w=0):to(t),nxt(n),w(w){}
}E[N*5];
int tot,head[N*5];
int vis[N],d[N];
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int w)
{
    E[tot] = edge(v,head[u],w);
    head[u] = tot++;
}
struct node{
    int v,w;
    node(int v=0,int w=0):v(v),w(w){}
    bool operator < (const node & p)const{
        return w > p.w;
    }
};
void Dijkstra(int s)
{
    memset(vis,0,sizeof(vis));
    memset(d,0x3f,sizeof(d));
    priority_queue<node> q;
    d[s] = 0;
    q.push(node(s,d[s]));
    while(!q.empty())
    {
        int u = q.top().v;q.pop();
        if(vis[u])
            continue;
        vis[u] = 1;
        for(int i = head[u];~i;i = E[i].nxt)
        {
            int v = E[i].to,w = E[i].w;
            if(!vis[v] && d[v] > d[u] + w)
            {
                d[v] = d[u] + w;
                q.push(node(v,d[v]));
            }
        }
    }
}
int main()
{
    int n,m,u,v,w;
    while(~scanf("%d%d",&n,&m) && (n || m))
    {
        init();
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        Dijkstra(1);
        printf("%d\n",d[n]);
    }
    return 0;
}
```


DFS(因为是求总时间,只需将简单的深搜求最短路的方法,二维数组清零即可):

原始的DFS:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int INF=99999999;//正无穷
int minn;
int n,e[105][105],book[105];

void dfs(int cur,int dis)
{
    int j;
    //已经超过前面查找的最短路径,就不需要在查找了
    if(dis>minn)
        return;
    if(cur==n)//到达了
    {
        minn=min(dis,minn);
        return;
    }

    for(j=1;j<=n;j++)//从1号城市到n号城市依次尝试
    {//判断当前城市cur到城市j是否有路,并判断城市j是否已经走过
        if(e[cur][j]!=INF&&book[j]==0)
        {
            book[j]=1;//标记已经走过
            dfs(j,dis+e[cur][j]);//从城市j再出发,继续寻找
            book[j]=0;
        }
    }
    return;
}
int main()
{
    int i,j,m,a,b,c;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
    //初始化二维矩阵
    memset(book,0,sizeof(book));
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(i==j)    e[i][j]=0;//自己
                else    e[i][j]=INF;

            //读入城市之间的距离
            for(i=1;i<=m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                e[a][b]=c;
                e[b][a]=c;
            }
            minn=INF;
            //从1号城市出发
            book[1]=1;
            dfs(1,0);
            printf("%d\n",minn);
    }
    return 0;
}
/*
5  8//五个城市,10条路径
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3
*/



修改后的DFS:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int INF = 999999;
int minn;
int n,m,e[105][105],book[105];

void dfs(int cur,int dis)
{
    int j;
    if(dis>minn)
        return;
    if(cur==n)//到达了终点
    {
        minn=dis;
        return;
    }
    for(int i=2;i<=n;i++)
    {
        if(e[cur][i]&&!book[i])
        {
            book[i]=1;
            dfs(i,dis+e[cur][i]);
            book[i]=0;//回溯
        }
    }
    return;
}
int main()
{

    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        memset(e,0,sizeof(e));
        memset(book,0,sizeof(book));

        int a,b,c;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            e[a][b]=c;
            e[b][a]=c;
        }
        //book[1]=1;
        minn=INF;
        dfs(1,0);
        printf("%d\n",minn);
    }
    return 0;
}

Dijkstra:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF = 99999999;
int main()
{
    int e[105][105],dis[105],book[105];
    int n,m;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i==j)    e[i][j]=0;
                    else    e[i][j]=INF;
        int t1,t2,t3;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            e[t1][t2]=t3;//双向边
            e[t2][t1]=t3;
        }

        //初始化dis数组,哲理是1号顶点到其余各顶点的初始路程
        for(int i=1;i<=n;i++)
            dis[i]=e[1][i];

        memset(book,0,sizeof(book));//初始化
        book[1]=0;//因为1点是源点

        int minn,u,v;
        //Dijkstra算法核心语句
        for(int i=1;i<=n-1;i++)//n-1
        {
            //找到离1号顶点最近的顶点
            //是每次都要找
            minn=INF;
            for(int j=1;j<=n;j++)
            {
                if(book[j]==0&&dis[j]<minn)
                {
                    minn=dis[j];
                    u=j;
                }
            }
            book[u]=1;//一个新的起点
            for(v=1;v<=n;v++)
            {
                if(e[u][v]<INF)
                {
                    if(dis[v]>dis[u]+e[u][v])
                        dis[v]=dis[u]+e[u][v];
                }
            }
        }

        //输出
            printf("%d\n",dis[n]);
    }
    return 0;
}
/*
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
*/

 Floyd:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF = 99999999;
int main()
{
    int e[105][105],dis[105],book[105];
    int n,m;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i==j)    e[i][j]=0;
                    else    e[i][j]=INF;
        int t1,t2,t3;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            e[t1][t2]=t3;//双向边
            e[t2][t1]=t3;
        }
        memset(book,0,sizeof(book));//初始化
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
         printf("%d\n",e[1][n]);
    }
    return 0;
}
/*
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值