題目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;
}