hdu 2544 最短路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544

Dijkstra:

/*
Dijkstra   留存
把时间看成距离
dis[i]表示起点到i点的最短距离。
*/
#include<stdio.h>
#include<string.h>
#define M 300000
int map[200][200],dis[1000],vis[1000];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
        break;
        else
        {
            int i,j;
            for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            map[i][j]=M;
            memset(vis,0,sizeof(vis));
            while(m--)
            {
                int a,b,t;
                scanf("%d%d%d",&a,&b,&t);
                if(map[a][b]>t)//使map[a][b]为给的最小   防止重边
                {
                    map[a][b]=t;
                    map[b][a]=t;
                }
            }
            for(i=1;i<=n;i++) dis[i]=(i==1?0:M);
            for(i=1;i<=n;i++)
            {
                int x,y,mm=M;
                for(y=1;y<=n;y++)
                {
                    if(!vis[y]&&dis[y]<mm)
                    {
                        x=y;
                        mm=dis[y];
                    }
                }//在所有节点中,找出dis最小的
                vis[x]=1;
                for(y=1;y<=n;y++)
                {
                    int temp=dis[x]+map[x][y];
                    if(temp<dis[y])
                    dis[y]=temp;
                }//再从x出发找边并更新dis[y]
            }
            printf("%d\n",dis[n]);
        }
    }
    return 0;
}

Floyd:

/*

  DP吧

*/

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 1000000000
int n,m,map[101][101],a,b,c;
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
        break;
        else
        {
            int i,j,k;
            for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            map[i][j]=M;

            for(i=1;i<=m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                if(map[a][b]>c)
                map[a][b]=map[b][a]=c;
            }

            for(k=1;k<=n;k++)
            for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            map[i][j]=min(map[i][j],map[i][k]+map[k][j]);

            printf("%d\n",map[1][n]);
        }
    }
    return 0;
}

SPFA(邻接矩阵)

/*

感觉dijsktra和spfa很像,关键都是松弛操作。但dijskra每次要把所有的点都试一遍(第二重循环),但spfa只检查和他相连的。


SPFA,先把起点入队,每次操作弹出第一个元素,对他所连接的点进行判断,如果需要进行松弛操作,就进行,并把这个点入队。

*/

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define M 1000000000
int n,m,a,b,c,dis[101],map[101][101];
vector<int>e[101];
void spfa()
{
    int i;
    for(i=1;i<=n;i++)
    dis[i]=M;
    dis[1]=0;
    queue<int>q;
    q.push(1);
    while(!q.empty())
    {
        int w=q.front();
        q.pop();
        for(i=0;i<e[w].size();i++)
        {
            if(dis[e[w][i]]>dis[w]+map[w][e[w][i]])
            {
                dis[e[w][i]]=dis[w]+map[w][e[w][i]];
                q.push(e[w][i]);
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
        break;
        else
        {
            int i;
            for(i=1;i<=n;i++)
            e[i].clear();

            for(i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            map[i][j]=M;

            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                if(map[a][b]>c)
                {
                    e[a].push_back(b);
                    e[b].push_back(a);
                    map[a][b]=map[b][a]=c;
                }
            }

            spfa();

            printf("%d\n",dis[n]);
        }
    }
    return 0;
}



Spfa(邻接表)

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define M 1000000000
int n,m,a,b,c,dis[101];
struct node
{
    int s,e,w;
};
vector<node>edge[101];
queue<int>q;

void init()
{
    int i;
    for(i=1;i<=100;i++)//注意清空时,不是n,是n的最大值
    edge[i].clear();

    while(!q.empty())
    q.pop();

    for(i=1;i<=n;i++)
    dis[i]=M;
    dis[1]=0;
}

void spfa()
{
    q.push(1);
    while(!q.empty())
    {
        int w=q.front();
        q.pop();
        for(int i=0;i<edge[w].size();i++)
        {
            node p=edge[w][i];
            if(p.w+dis[w]<dis[p.e])
            {
                dis[p.e]=p.w+dis[w];
                q.push(p.e);
            }
        }
    }

}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
        break;
        else
        {
            init();
            int i;
            for(i=1;i<=m;i++)
            {
                node d,f;
                scanf("%d%d%d",&a,&b,&c);
                d.s=f.e=a;
                d.e=f.s=b;
                d.w=f.w=c;
                edge[a].push_back(d);
                edge[b].push_back(f);
            }
            spfa();

            printf("%d\n",dis[n]);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值