最短路习题集(hdu)

下面把在杭电刷题的最短路的代码贴上

hdu 2544

点击打开链接

 

dijkstra算法
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define N 200
#define Y 33333110
using namespace std;
int mapp[N][N],mark[N],dist[N],n,m;
void dijstra(){
    int i,j,minn,k;
    for(i=1;i<=n;i++)
        dist[i]=mapp[1][i];
    mark[1]=1;
    dist[1]=0;
    for(i=1;i<n;i++){
        minn=Y;k=-1;
        for(j=1;j<=n;j++)
            if(mark[j]==0&&minn>dist[j]){
                minn=dist[j];
                k=j;
            }
        mark[k]=1;
        if(k!=-1){
            for(j=1;j<=n;j++)
                if(mark[j]==0&&mapp[k][j]<Y&&mapp[k][j]+dist[k]<dist[j])
                dist[j]=mapp[k][j]+dist[k];
        }
    }

}
int main()
{
    int i,j,a,b,c;
    while(cin>>n>>m&&n&&m){
        memset(mark,0,sizeof(mark));
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            mapp[i][j]=Y;
        for(i=1;i<=m;i++){
            cin>>a>>b>>c;
            //if(mapp[a][b]>c)
            mapp[a][b]=mapp[b][a]=c;
        }
        dijstra();
        cout<<dist[n]<<endl;
    }
    return 0;
}
floyd算法
/****
杭电最短路2544    http://acm.hdu.edu.cn/showproblem.php?pid=2544 
****/
#include <iostream>
#include <string.h>
#define N 1100
#define Y 0x3f3f3f3f
using namespace std;
int mapp[N][N];
int main()
{
    int n,m,a,b,c,i,j,k;
    while(cin>>n>>m&&n&&m){
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++)
            mapp[i][j]=Y;
        mapp[i][i]=0;
    }
    for(i=0;i<m;i++){
        cin>>a>>b>>c;
        mapp[a][b]=mapp[b][a]=c;
    }
    for(k=1;k<=n;k++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)    ///松弛 
                if(mapp[i][j]>(mapp[i][k]+mapp[k][j]))
                    mapp[i][j]=mapp[i][k]+mapp[k][j];
    cout<<mapp[1][n]<<endl;
    }
    return 0;
}
SPFA算法
#include <iostream>
#include <string.h>
#include <queue>
#define N 600
#define maxEdgeNum 10010//最多边条数
#define inf 0x3f3f3f3f
using namespace std;
int n,m,dis[N],mapp[N][N],vis[N];
void SPFA(int start)
{
  queue<int>q;
  int i,u;
  memset(vis,0,sizeof(vis));    memset(dis,inf,sizeof(dis));
  dis[start]=0;
  q.push(start);    vis[start]=1;
  //第二步:在队列中取点,把其vis状态设为0,对该点相邻的点(连接二者的边)进行松弛操作,修改相邻点的dis[]
  //并判断相邻的点vis[]状态是否为0(不存在于队列中),如果是,将其加入到队列中
  while(!q.empty())
  {
    u=q.front(); q.pop();    vis[u]=0;
    ///松弛
    for(i=1;i<=n;i++)
      if(dis[u]+mapp[u][i]<dis[i])
      {
        dis[i]=dis[u]+mapp[u][i];
        if(!vis[i])//要写在松弛成功的里面
        {
          q.push(i);
          vis[i]=1;
        }
      }
  }
}
int main()
{
  int s,t;
  while(cin>>n>>m&&n&&m)
  {
    int from,to,w,i;
    memset(mapp,inf,sizeof(mapp));//初始化
    for(i=1;i<=m;i++)//无向图,一条无向边看为两条有向边
    {
      cin>>from>>to>>w;
      if(mapp[from][to]>w)
        mapp[from][to]=mapp[to][from]=w;
    }
    //cin>>s>>t;
    SPFA(1);
    if(dis[n]>=inf)
        cout<<"-1"<<endl;
    else
        cout<<dis[n]<<endl;
  }
  return 0;
}

hdu 2112 这个题目有点特殊,因为节点的编号不是数字而是字母,起始终止节点的编号也是字符串,用了map,不会的请戳点击打开链接

 

点击打开链接

 

dijkstar算法
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
#define N 0x1f1f1f1f
int mapp[151][151],d[155],mark[151],ans;
char s1[31],s2[31];
void Dij(){
    int i,j,k,minn;
    memset(mark,0,sizeof(mark));
    for(i=1;i<ans;i++)
        d[i]=mapp[1][i];
        d[1]=0; mark[1]=1;
        for(i=1;i<=ans;i++){
            minn=N; k=-1;
            for(j=1;j<=ans;j++)
                if(minn>d[j]&&!mark[j]){
                    minn=d[j];
                    k=j;
                }
            mark[k]=1;
            if(k!=-1)
            for(j=1;j<=ans;j++){
                if(!mark[j]&&mapp[k][j]<N)
                d[j]=min(d[j],d[k]+mapp[k][j]);
            }
        }
}
int main()
{
    int i,j,c,n,k;
    map<string,int> M;
    while(scanf("%d",&n)&&n!=-1){
        k=0,ans=3;
        M.clear();//初始化。
        scanf("%s%s",s1,s2);
        if(!strcmp(s1,s2))  k=1;//若起始终止节点相等,则k为1,即一种状态
        M[s1]=1,M[s2]=2;
        for(i=1;i<=150;i++)
            for(j=1;j<=150;j++)
                mapp[i][j]=mapp[j][i]=N;
        while(n--)  {
            scanf("%s%s%d",s1,s2,&c);
            if(!M[s1]) M[s1]=ans++;
            if(!M[s2]) M[s2]=ans++;
            mapp[M[s1]][M[s2]]=mapp[M[s2]][M[s1]]=min(mapp[M[s1]][M[s2]],c);
        }
        if(k==1)  printf("0\n");
        else {
            Dij();
            if(d[2]<N)
                printf("%d\n",d[2]);
            else
                printf("-1\n");
            }
    }
    return 0;
}

hdu 1874

 

点击打开链接

 

#include <iostream>
#include <queue>
#include <string.h>
#define Y 111100
#define N 1100
using namespace std;
int mapp[N][N],mark[N],dist[N],n,m,s,t;
void dijsta(int v0){
    int i,j;
    for(i=0;i<n;i++)
        dist[i]=mapp[v0][i];
    mark[v0]=1;  dist[v0]=0;
    for(i=1;i<n;i++){
        int minn=Y,k=-1;
        for(j=0;j<n;j++)
            if(minn>dist[j]&&mark[j]==0)
            {   minn=dist[j];
                k=j;
            }
        mark[k]=1;
        if(k!=-1){
            for(j=0;j<n;j++)
                if(mapp[k][j]<Y&&mark[j]==0){
                    if(dist[k]+mapp[k][j]<dist[j])//更新
                        dist[j]=dist[k]+mapp[k][j];
                }
        }
    }
}
int main()
{
    int a,b,c,i,j,y=0;
    while(cin>>n>>m){
        memset(mark,0,sizeof(mark));
        memset(dist,0,sizeof(dist));
       //将邻接矩阵初始化为无穷大
      for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                mapp[i][j]=Y;
            }
        }
        for(i=0;i<m;i++){
            cin>>a>>b>>c;
            if(mapp[a][b]>c)
            mapp[a][b]=mapp[b][a]=c;
        }
        cin>>s>>t;//输入起始点与终止点的编号
        dijsta(s);//从起始点开始寻找最短路
        y=dist[t];//dist[i]表示从起始点到i的最短距离
        if(y==Y)
            cout<<"-1"<<endl;
        else
            cout<<y<<endl;
    }

    return 0;
}

poj 1789 每行固定7的字符,每两行不同字符的个数为两行标号之间的距离

 

点击打开链接

 

#include <iostream>
#include <Stdio.h>
#include <string.h>
#define N 10009
#define Y 0x3f3f3f3f
using namespace std;
int dist[N],n,mapp[N][N],mark[N];
int dijkstar(){
	int i,j,minn,k,sum=0;
	for(i=0;i<n;i++)
	dist[i]=mapp[0][i];
	dist[0]=0,mark[0]=1;
	for(i=1;i<n;i++){
		minn=Y,k=-1;
		for(j=0;j<n;j++)
			if(dist[j]<minn&&mark[j]==0){
				minn=dist[j];
				k=j;
			}
		mark[k]=1;
		if(k!=-1){
			sum+=dist[k];
			for(j=0;j<n;j++)
			if(mark[j]==0&&mapp[k][j]<dist[j])
			dist[j]=mapp[k][j];
		}
	}
	return sum;
}
int main()
{
    int m,i,j,k,l,y;
    char s[2010][10];
    while(scanf("%d",&n)&&n){
    	memset(mark,0,sizeof(mark));
    	getchar();
		for(i=0;i<n;i++)
			gets(s[i]);
		 for (i=0;i<n-1;i++){
            for(j=i+1;j<n;j++){
            	l=0;
                 for (k=0;k<7;k++)
                     if(s[i][k]!=s[j][k])
                         l++;
				mapp[j][i]=mapp[i][j]=l;
            }
         }
		 for(i=0;i<n;i++)
		 	for(j=0;j<n;j++)
		 	if(mapp[i][j]==0)
		 	mapp[i][j]=Y;
		y=dijkstar();
		printf("The highest possible quality is 1/%d.\n",y);	
	}
    return 0;
}

hdu 1596

 

点击打开链接

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <iomanip>
#define N 11100
using namespace std;
double mapp[N][N],dist[N];
int mark[N],n;
void dij(int v0){
    int i,j,k;
    double minn;
    for(i=1;i<=n;i++)
        dist[i]=mapp[v0][i];
    dist[v0]=0; mark[v0]=1;
    for(i=1;i<n;i++){
        minn=0; k=-1;
        for(j=1;j<=n;j++)
            if(dist[j]>minn&&mark[j]==0){
                minn=dist[j];
                k=j;
            }
        mark[k]=1;
        if(k!=-1)
            for(j=1;j<=n;j++)
                if(!mark[j]&&dist[k]*mapp[k][j]>dist[j])
                   dist[j]=dist[k]*mapp[k][j];
    }
}
int main()
{
    int i,j,m,a,b;
    while(scanf("%d",&n)!=EOF){
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        scanf("%lf",&mapp[i][j]);
    scanf("%d",&m);
    for(i=0;i<m;i++){
        memset(mark,0,sizeof(mark));
        scanf("%d %d",&a,&b);
        dij(a);
        if(dist[b]==0)
            printf("What a pity!\n");
        else
            printf("%.3lf\n",dist[b]);
        }
    }
    return 0;
}

 

 

 

 

 

 



 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值