hdoj-1874 畅通工程续【最短路径--dijkstra&&floyd&&spfa】

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1874

本题需要注意的地方是

起点终点并不是第一个 最后一个 是另外给定的

如果不存在从S到T的路线,就输出-1    说明S和T之间无道路连通  T到S的距离(即dis[t])为INF

 

dijkstra:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 222
#define INF 0x3f3f3f3f
using namespace std;
int n,m,dis[maxn],map[maxn][maxn];
bool visit[maxn];

void dijkstra(int start)
{
    int i,j,next;
    memset(visit,0,sizeof(visit));//初始化 
    for(i=0;i<n;i++)
        dis[i]=map[start][i];//dis[]表示i到start的距离  main()中已对map[][]初始化 这里初始化dis=INF 
    visit[start]=true;
    dis[start]=0;
    for(i=1;i<n;i++)
    {
        int temp=INF;
        for(j=0;j<n;j++)
        {
            if(!visit[j]&&dis[j]<temp)
            {
                temp=dis[j];
                next=j;
            }
        }
        visit[next]=true;
        for(j=0;j<n;j++)
        {
            if(!visit[j])
                dis[j]=min(dis[j],dis[next]+map[next][j]);
        }
    }
}

int main()
{
    int a,b,x,s,t,i,j;
    while(~scanf("%d%d",&n,&m))
    {
        memset(map,INF,sizeof(map));//或者下面注释的9行 
//        for(i=0;i<n;i++)
//        {
//            for(j=0;j<n;j++)
//            {
//                if(i==j)
//                    map[i][j]=0;
//                else map[i][j]=INF;
//            }
//        }
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&x);
            if(map[a][b]>x)
                map[a][b]=map[b][a]=x;
        }
        scanf("%d%d",&s,&t);
        dijkstra(s);
        if(dis[t]==INF)
            printf("-1\n");
        else printf("%d\n",dis[t]);
    }
}

floyd:

三个for循环

#include<stdio.h>
#define INF 0x3f3f3f3f
int n,m,path[220][220];
void floyd()
{
    int i,j,k;
    for(k=0;k<n;k++)
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
            {
                if(path[i][j]>path[i][k]+path[k][j])
                    path[i][j]=path[i][k]+path[k][j];        
            }
}

void init()
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            if(i==j)
                path[i][j]=0;
            else path[i][j]=INF;
        }
}

void getmap()
{
    int a,b,x;
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&x);
        if(path[a][b]>x)
            path[a][b]=path[b][a]=x;
    }
}

int main()
{
    int s,t;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        getmap();
        floyd();
        scanf("%d%d",&s,&t);
        if(path[s][t]<INF)
            printf("%d\n",path[s][t]);
        else printf("-1\n");
    }
    return 0;
}

spfa:

#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXN 200+20//点数 
#define MAXM 2000+20//边数 
using namespace std;
int n,m,top,vis[MAXN],dis[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++;
 node E={u,v,w,head[u]};
 edge[top]=E;
 head[u]=top++;
}

void spfa(int s,int e)//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;
    }
   }
  }
 }
 if(dis[e]==INF)
  printf("-1\n");
 else 
  printf("%d\n",dis[e]);
}

void getmap()
{
 int a,b,x;
 while(m--)
 { 
  scanf("%d%d%d",&a,&b,&x);
  add(a,b,x);
  add(b,a,x);//无向图  既可由a->b,也可由b->a; 
 }
}

int main()
{
 while(~scanf("%d%d",&n,&m))//n|m位运算符  n==0&&m==0时输入结束 
 {
  int start,end;
  init();
  getmap();
  scanf("%d%d",&start,&end);
  spfa(start,end);
 }
 return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值