hdoj-2544 最短路【最短路徑--dijkstra&&spfa&&floyd】

題目http://acm.hdu.edu.cn/showproblem.php?pid=2544

模板題三種解題方法

dijkstra:

#include<cstdio>
#include<cstring>//memset
#include<algorithm>//min
#define INF 0x3f3f3f3f
#define maxn 110
using namespace std;//algorithm
int n,m,map[maxn][maxn],dis[maxn];//map[][]兩點之間的距離  dis[]起始點(源點)到當前點的距離 
bool visit[maxn];//判斷該點是否被訪問 

void dijkstra(int s)
{
	int next;//下一個進入(最短距離) V集合的點 
	memset(visit,0,sizeof(visit));// 一開始 V集合中無任何元素 
//	memset(map,INF,sizeof(map));
	for(int i=1;i<=n;i++)//dis初始化  起始點(源點)到當前點的距離 
		dis[i]=map[s][i];
	visit[s]=true;//將源點放入集合V 
	dis[s]=0;//源點到源點的距離爲0 
	for(int i=1;i<n;i++)//已經把U集合中的一個點存入V集合 最多進行n-1次尋找最小值 
	{
		int temp=INF;// 一開始默認兩點之間的距離爲INF 
		for(int u=1;u<=n;u++)
		{
			if(!visit[u]&&dis[u]<temp)//找最小值(該點不在V集合 並且 該點到源點的距離小於 當前值 ) 
			{
				temp=dis[u];
				next=u;
			}
		}
		visit[next]=true;//將離源點最近的點存入V集合 
		for(int u=1;u<=n;u++)//鬆弛 
		{
			if(!visit[u])
				dis[u]=min(dis[u],dis[next]+map[next][u]);
		}
	}
}

int main()
{
	int a,b,c;
	while(scanf("%d%d",&n,&m),n,m)
	{
		memset(map,INF,sizeof(map));// 不能在dijkstra()中初始化  對map[][]賦值前初始化 
		while(m--)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(map[a][b]>c)//避免重複   上面初始化爲INF map仍爲INF表示未走過這條路   
				map[a][b]=map[b][a]=c;
		}
		dijkstra(1);
		printf("%d\n",dis[n]);
	}
	return 0;
}

 

spfa:

#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXN 100+10//點數 
#define MAXM 20000+10//邊數 
using namespace std;
int n,m,top,vis[MAXN],dis[MAXN],visit[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++;
}


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

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

int main()
{
	while(scanf("%d%d",&n,&m),n|m)//n|m位運算符  n==0&&m==0時輸入結束 
	{
		init();
		getmap();
		spfa(1);
	
	}
	return 0;
}

floyd:

#include<stdio.h>
#define INF 0x3f3f3f3f
int n,m,path[110][110];

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

void floyd()
{
    int i,j,k;
    for(k=1;k<=n;k++)//K是窮舉i,j的斷點  必須是最外層表示斷點 
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                if(path[i][j]>path[i][k]+path[k][j])
                    path[i][j]=path[i][k]+path[k][j];
            }
}

void getmap()
{
    int a,b,c;
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        if(path[a][b]>c)//防止重複  一開始初始化爲INF 若已經選過 則不滿足if 
            path[a][b]=path[b][a]=c;
    }
}

int main()
{
    while(scanf("%d%d",&n,&m),n|m)
    {
        init();
        getmap();
        floyd();
        printf("%d\n",path[1][n]);
    }
    return 0;
}



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章